// Daniel Morgan (danmorg@sc.rr.com)
// Tim Coleman (tim@timcoleman.com)
// Diego Caravana (diego@toth.it)
+// Umadevi S (sumadevi@novell.com)
+// Amit Biswas (amit@amitbiswas.com)
//
// (C) Ximian, Inc. 2002
// Copyright (C) Tim Coleman, 2002
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using Mono.Data.Tds;
using Mono.Data.Tds.Protocol;
using System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
+using System.Data.SqlTypes;
using System.Runtime.InteropServices;
using System.Text;
namespace System.Data.SqlClient {
- [TypeConverterAttribute ("System.Data.SqlClient.SqlParameterConverter, "+ Consts.AssemblySystem_Data)]
+ [TypeConverterAttribute (typeof (SqlParameterConverter))]
+#if NET_2_0
+ public sealed class SqlParameter : DbParameter, IDbDataParameter, IDataParameter, ICloneable
+#else
public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
+#endif // NET_2_0
{
#region Fields
DbType dbType;
ParameterDirection direction = ParameterDirection.Input;
bool isNullable;
- bool isSizeSet = false;
bool isTypeSet = false;
int offset;
SqlDbType sqlDbType;
string sourceColumn;
DataRowVersion sourceVersion;
+ SqlCompareOptions compareInfo;
+ int localeId;
+ Object sqlValue;
+ string udtTypeName;
+#if NET_2_0
+ bool sourceColumnNullMapping;
+ string xmlSchemaCollectionDatabase = String.Empty;
+ string xmlSchemaCollectionOwningSchema = String.Empty;
+ string xmlSchemaCollectionName = String.Empty;
+#endif
#endregion // Fields
public SqlParameter ()
: this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
{
+ isTypeSet = false;
}
public SqlParameter (string parameterName, object value)
{
- metaParameter = new TdsMetaParameter (parameterName, value);
+ metaParameter = new TdsMetaParameter (parameterName, value);
+ InferSqlType (value);
+ metaParameter.Value = SqlTypeToFrameworkType(value);
this.sourceVersion = DataRowVersion.Current;
- InferSqlType (value);
}
public SqlParameter (string parameterName, SqlDbType dbType)
[EditorBrowsable (EditorBrowsableState.Advanced)]
public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
{
- metaParameter = new TdsMetaParameter (parameterName, size, isNullable, precision, scale, value);
-
- SqlDbType = dbType;
+ metaParameter = new TdsMetaParameter (parameterName, size,
+ isNullable, precision,
+ scale,
+ value);
+ if (dbType != SqlDbType.Variant)
+ SqlDbType = dbType;
+ metaParameter.Value = SqlTypeToFrameworkType (value);
Direction = direction;
SourceColumn = sourceColumn;
SourceVersion = sourceVersion;
}
+#if NET_2_0
+ public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, Object value, string xmlSchemaCollectionDatabase, string xmlSchemaCollectionOwningSchema, string xmlSchemaCollectionName)
+ : this (parameterName, dbType, size, direction, false, precision, scale, sourceColumn, sourceVersion, value)
+ {
+ XmlSchemaCollectionDatabase = xmlSchemaCollectionDatabase;
+ XmlSchemaCollectionOwningSchema = xmlSchemaCollectionOwningSchema;
+ XmlSchemaCollectionName = xmlSchemaCollectionName;
+ SourceColumnNullMapping = sourceColumnNullMapping;
+ }
+#endif
+
// This constructor is used internally to construct a
// SqlParameter. The value array comes from sp_procedure_params_rowset.
// This is in SqlCommand.DeriveParameters.
- internal SqlParameter (object[] dbValues)
+ internal SqlParameter (object[] dbValues)
+ : this (dbValues [3].ToString (), String.Empty)
{
- Precision = 0;
+ Precision = 0;
Scale = 0;
Direction = ParameterDirection.Input;
case 4:
Direction = ParameterDirection.ReturnValue;
break;
+ default:
+ Direction = ParameterDirection.Input;
+ break;
}
+ IsNullable = (dbValues [8] != null &&
+ dbValues [8] != DBNull.Value) ? (bool) dbValues [8] : false;
- IsNullable = (bool) dbValues[8];
+ if (dbValues [12] != null && dbValues [12] != DBNull.Value)
+ Precision = (byte) ((short) dbValues [12]);
- if (dbValues[12] != null)
- Precision = (byte) ((short) dbValues[12]);
- if (dbValues[13] != null)
- Scale = (byte) ((short) dbValues[13]);
+ if (dbValues [13] != null && dbValues [13] != DBNull.Value)
+ Scale = (byte) ( (short) dbValues [13]);
- SetDbTypeName ((string) dbValues[16]);
+ SetDbTypeName ((string) dbValues [16]);
}
#endregion // Constructors
set { container = value; }
}
+ internal void CheckIfInitialized ()
+ {
+ if (!isTypeSet)
+ throw new Exception ("all parameters to have an explicity set type");
+
+ if (MetaParameter.IsVariableSizeType) {
+ if (SqlDbType == SqlDbType.Decimal && Precision == 0)
+ throw new Exception ("Parameter of type 'Decimal' have an explicitly set Precision and Scale");
+ else if (Size == 0)
+ throw new Exception ("all variable length parameters to have an explicitly set non-zero Size");
+ }
+ }
+
+#if ONLY_1_0 || ONLY_1_1
[Browsable (false)]
- [DataCategory ("Data")]
[DataSysDescription ("The parameter generic type.")]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[RefreshProperties (RefreshProperties.All)]
- public DbType DbType {
+ [DataCategory ("Data")]
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ DbType DbType {
get { return dbType; }
set {
SetDbType (value);
}
}
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("Input, output, or bidirectional parameter.")]
[DefaultValue (ParameterDirection.Input)]
- public ParameterDirection Direction {
+#endif
+#if NET_2_0
+ [RefreshProperties (RefreshProperties.All)]
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ ParameterDirection Direction {
get { return direction; }
set {
direction = value;
get { return metaParameter; }
}
- string IDataParameter.ParameterName {
- get { return metaParameter.ParameterName; }
- set { metaParameter.ParameterName = value; }
- }
-
+#if ONLY_1_0 || ONLY_1_1
[Browsable (false)]
[DataSysDescription ("a design-time property used for strongly typed code-generation.")]
[DefaultValue (false)]
[DesignOnly (true)]
[EditorBrowsable (EditorBrowsableState.Advanced)]
- public bool IsNullable {
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ bool IsNullable {
get { return metaParameter.IsNullable; }
set { metaParameter.IsNullable = value; }
}
[Browsable (false)]
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("Offset in variable length data types.")]
[DefaultValue (0)]
+#endif
+#if NET_2_0
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
public int Offset {
get { return offset; }
set { offset = value; }
}
-
+
+#if ONLY_1_0 || ONLY_1_1
[DataSysDescription ("Name of the parameter, like '@p1'")]
[DefaultValue ("")]
- public string ParameterName {
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ string ParameterName {
get { return metaParameter.ParameterName; }
set { metaParameter.ParameterName = value; }
}
+ [DefaultValue (0)]
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
- [DefaultValue (0)]
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+#endif
public byte Precision {
get { return metaParameter.Precision; }
set { metaParameter.Precision = value; }
}
+ [DefaultValue (0)]
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
- [DefaultValue (0)]
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+#endif
public byte Scale {
get { return metaParameter.Scale; }
set { metaParameter.Scale = value; }
}
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
- [DataSysDescription ("Size of variable length datatypes (strings & arrays).")]
+ [DataSysDescription ("Size of variable length data types (string & arrays).")]
[DefaultValue (0)]
- public int Size {
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ int Size {
get { return metaParameter.Size; }
set { metaParameter.Size = value; }
}
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("When used by a DataAdapter.Update, the source column name that is used to find the DataSetColumn name in the ColumnMappings. This is to copy a value between the parameter and a datarow.")]
[DefaultValue ("")]
- public string SourceColumn {
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ string SourceColumn {
get { return sourceColumn; }
set { sourceColumn = value; }
}
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
[DefaultValue (DataRowVersion.Current)]
- public DataRowVersion SourceVersion {
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ DataRowVersion SourceVersion {
get { return sourceVersion; }
set { sourceVersion = value; }
}
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("The parameter native type.")]
[DefaultValue (SqlDbType.NVarChar)]
+#endif
[RefreshProperties (RefreshProperties.All)]
+#if NET_2_0
+ [DbProviderSpecificTypeProperty(true)]
+#endif
public SqlDbType SqlDbType {
get { return sqlDbType; }
set {
}
}
+ [TypeConverterAttribute (typeof (StringConverter))]
+#if ONLY_1_0 || ONLY_1_1
[DataCategory ("Data")]
[DataSysDescription ("Value of the parameter.")]
[DefaultValue (null)]
- [TypeConverterAttribute ("System.ComponentModel.StringConverter, "+ Consts.AssemblySystem)]
- public object Value {
+#else
+ [RefreshProperties (RefreshProperties.All)]
+#endif
+ public
+#if NET_2_0
+ override
+#endif // NET_2_0
+ object Value {
get { return metaParameter.Value; }
set {
if (!isTypeSet)
InferSqlType (value);
- metaParameter.Value = value;
+ metaParameter.Value = SqlTypeToFrameworkType (value);
}
}
+#if NET_2_0
+ [Browsable (false)]
+ public SqlCompareOptions CompareInfo{
+ get{ return compareInfo; }
+ set{ compareInfo = value; }
+ }
+
+ [Browsable (false)]
+ public int LocaleId {
+ get { return localeId; }
+ set { localeId = value; }
+ }
+
+ [Browsable (false)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ public Object SqlValue {
+ get { return sqlValue; }
+ set { sqlValue = value; }
+ }
+
+ public override bool SourceColumnNullMapping {
+ get { return sourceColumnNullMapping; }
+ set { sourceColumnNullMapping = value; }
+ }
+
+ public string XmlSchemaCollectionDatabase {
+ get { return xmlSchemaCollectionDatabase; }
+ set { xmlSchemaCollectionDatabase = (value == null ? String.Empty : value); }
+ }
+
+ public string XmlSchemaCollectionName {
+ get { return xmlSchemaCollectionName; }
+ set {
+ xmlSchemaCollectionName = (value == null ? String.Empty : value);
+ }
+ }
+
+ public string XmlSchemaCollectionOwningSchema {
+ get { return xmlSchemaCollectionOwningSchema; }
+ set {
+ xmlSchemaCollectionOwningSchema = (value == null ? String.Empty : value);
+ }
+ }
+#endif
#endregion // Properties
#region Methods
// infer type information.
private void InferSqlType (object value)
{
- Type type = value.GetType ();
+ if (value == null || value == DBNull.Value) {
+ SetSqlDbType (SqlDbType.NVarChar);
+ return;
+ }
+ Type type = value.GetType ();
string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
switch (type.FullName) {
case "System.Int64":
+ case "System.Data.SqlTypes.SqlInt64":
SetSqlDbType (SqlDbType.BigInt);
break;
case "System.Boolean":
+ case "System.Data.SqlTypes.SqlBoolean":
SetSqlDbType (SqlDbType.Bit);
break;
case "System.String":
+ case "System.Data.SqlTypes.SqlString":
SetSqlDbType (SqlDbType.NVarChar);
break;
case "System.DateTime":
+ case "System.Data.SqlTypes.SqlDateTime":
SetSqlDbType (SqlDbType.DateTime);
break;
case "System.Decimal":
+ case "System.Data.SqlTypes.SqlDecimal":
SetSqlDbType (SqlDbType.Decimal);
break;
case "System.Double":
+ case "System.Data.SqlTypes.SqlDouble":
SetSqlDbType (SqlDbType.Float);
break;
case "System.Byte[]":
+ case "System.Data.SqlTypes.SqlBinary":
SetSqlDbType (SqlDbType.VarBinary);
break;
case "System.Byte":
+ case "System.Data.SqlTypes.SqlByte":
SetSqlDbType (SqlDbType.TinyInt);
break;
case "System.Int32":
+ case "System.Data.SqlTypes.SqlInt32":
SetSqlDbType (SqlDbType.Int);
break;
case "System.Single":
+ case "System.Data.SqlTypes.Single":
SetSqlDbType (SqlDbType.Real);
break;
case "System.Int16":
+ case "System.Data.SqlTypes.SqlInt16":
SetSqlDbType (SqlDbType.SmallInt);
break;
case "System.Guid":
+ case "System.Data.SqlTypes.SqlGuid":
SetSqlDbType (SqlDbType.UniqueIdentifier);
break;
+ case "System.Money":
+ case "System.SmallMoney":
+ case "System.Data.SqlTypes.SqlMoney":
+ SetSqlDbType (SqlDbType.Money);
+ break;
case "System.Object":
- SetSqlDbType (SqlDbType.Variant);
+ SetSqlDbType (SqlDbType.Variant);
break;
default:
throw new ArgumentException (exception);
case DbType.AnsiString:
MetaParameter.TypeName = "varchar";
sqlDbType = SqlDbType.VarChar;
+ MetaParameter.IsVariableSizeType = true;
break;
case DbType.AnsiStringFixedLength:
MetaParameter.TypeName = "char";
sqlDbType = SqlDbType.Char;
+ MetaParameter.IsVariableSizeType = true;
break;
case DbType.Binary:
MetaParameter.TypeName = "varbinary";
sqlDbType = SqlDbType.VarBinary;
+ MetaParameter.IsVariableSizeType = true;
break;
case DbType.Boolean:
MetaParameter.TypeName = "bit";
case DbType.String:
MetaParameter.TypeName = "nvarchar";
sqlDbType = SqlDbType.NVarChar;
+ MetaParameter.IsVariableSizeType = true;
break;
case DbType.StringFixedLength:
MetaParameter.TypeName = "nchar";
sqlDbType = SqlDbType.NChar;
+ MetaParameter.IsVariableSizeType = true;
break;
case DbType.Time:
MetaParameter.TypeName = "datetime";
case "varchar":
SqlDbType = SqlDbType.VarChar;
break;
+ case "sql_variant":
+ SqlDbType = SqlDbType.Variant;
+ break;
default:
SqlDbType = SqlDbType.Variant;
break;
case SqlDbType.Binary:
MetaParameter.TypeName = "binary";
dbType = DbType.Binary;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.Timestamp:
MetaParameter.TypeName = "timestamp";
case SqlDbType.VarBinary:
MetaParameter.TypeName = "varbinary";
dbType = DbType.Binary;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.Bit:
MetaParameter.TypeName = "bit";
case SqlDbType.Char:
MetaParameter.TypeName = "char";
dbType = DbType.AnsiStringFixedLength;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.DateTime:
MetaParameter.TypeName = "datetime";
case SqlDbType.Image:
MetaParameter.TypeName = "image";
dbType = DbType.Binary;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.Int:
MetaParameter.TypeName = "int";
case SqlDbType.NChar:
MetaParameter.TypeName = "nchar";
dbType = DbType.StringFixedLength;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.NText:
MetaParameter.TypeName = "ntext";
dbType = DbType.String;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.NVarChar:
MetaParameter.TypeName = "nvarchar";
dbType = DbType.String;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.Real:
MetaParameter.TypeName = "real";
case SqlDbType.Text:
MetaParameter.TypeName = "text";
dbType = DbType.AnsiString;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.VarChar:
MetaParameter.TypeName = "varchar";
dbType = DbType.AnsiString;
+ MetaParameter.IsVariableSizeType = true;
break;
case SqlDbType.TinyInt:
MetaParameter.TypeName = "tinyint";
return ParameterName;
}
+ private object SqlTypeToFrameworkType (object value)
+ {
+ if (! (value is INullable)) // if the value is not SqlType
+ return ConvertToFrameworkType (value);
+
+ // Map to .net type, as Mono TDS respects only types from .net
+ switch (value.GetType ().FullName) {
+ case "System.Data.SqlTypes.SqlBinary":
+ return ( (SqlBinary) value).Value;
+ case "System.Data.SqlTypes.SqlBoolean":
+ return ( (SqlBoolean) value).Value;
+ case "System.Data.SqlTypes.SqlByte":
+ return ( (SqlByte) value).Value;
+ case "System.Data.SqlTypes.SqlDateTime":
+ return ( (SqlDateTime) value).Value;
+ case "System.Data.SqlTypes.SqlDecimal":
+ return ( (SqlDecimal) value).Value;
+ case "System.Data.SqlTypes.SqlDouble":
+ return ( (SqlDouble) value).Value;
+ case "System.Data.SqlTypes.SqlGuid":
+ return ( (SqlGuid) value).Value;
+ case "System.Data.SqlTypes.SqlInt16":
+ return ( (SqlInt16) value).Value;
+ case "System.Data.SqlTypes.SqlInt32 ":
+ return ( (SqlInt32 ) value).Value;
+ case "System.Data.SqlTypes.SqlInt64":
+ return ( (SqlInt64) value).Value;
+ case "System.Data.SqlTypes.SqlMoney":
+ return ( (SqlMoney) value).Value;
+ case "System.Data.SqlTypes.SqlSingle":
+ return ( (SqlSingle) value).Value;
+ case "System.Data.SqlTypes.SqlString":
+ return ( (SqlString) value).Value;
+ }
+ return value;
+ }
+
+ private object ConvertToFrameworkType (object value)
+ {
+ if (value == null || value == DBNull.Value)
+ return value;
+ switch (sqlDbType) {
+ case SqlDbType.BigInt :
+ return Convert.ChangeType (value, typeof (Int64));
+ case SqlDbType.Binary:
+ case SqlDbType.VarBinary:
+ if (value is byte[])
+ return value;
+ break;
+ case SqlDbType.Bit:
+ return Convert.ChangeType (value, typeof (bool));
+ case SqlDbType.Int:
+ return Convert.ChangeType (value, typeof (Int32));
+ case SqlDbType.SmallInt :
+ return Convert.ChangeType (value, typeof (Int16));
+ case SqlDbType.TinyInt :
+ return Convert.ChangeType (value, typeof (byte));
+ case SqlDbType.Float:
+ return Convert.ChangeType (value, typeof (Double));
+ case SqlDbType.Real:
+ return Convert.ChangeType (value, typeof (Single));
+ case SqlDbType.Decimal:
+ return Convert.ChangeType (value, typeof (Decimal));
+ case SqlDbType.Money:
+ case SqlDbType.SmallMoney:
+ {
+ Decimal val = (Decimal)Convert.ChangeType (value, typeof (Decimal));
+ return Decimal.Round(val, 4);
+ }
+ case SqlDbType.DateTime:
+ case SqlDbType.SmallDateTime:
+ return Convert.ChangeType (value, typeof (DateTime));
+ case SqlDbType.VarChar:
+ case SqlDbType.NVarChar:
+ case SqlDbType.Char:
+ case SqlDbType.NChar:
+ case SqlDbType.Text:
+ case SqlDbType.NText:
+ return Convert.ChangeType (value, typeof (string));
+ case SqlDbType.UniqueIdentifier:
+ return Convert.ChangeType (value, typeof (Guid));
+ case SqlDbType.Variant:
+ return metaParameter.Value;
+ }
+ throw new NotImplementedException ("Type Not Supported : " + sqlDbType.ToString());
+ }
+
+#if NET_2_0
+
+ public override void ResetDbType ()
+ {
+ InferSqlType (metaParameter.Value);
+ }
+
+ public void ResetSqlDbType ()
+ {
+ InferSqlType (metaParameter.Value);
+ }
+#endif // NET_2_0
+
#endregion // Methods
}
}