2 // System.Data.SqlClient.SqlParameter.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
9 // (C) Ximian, Inc. 2002
10 // Copyright (C) Tim Coleman, 2002
13 using Mono.Data.Tds.Protocol;
15 using System.ComponentModel;
17 using System.Data.Common;
18 using System.Runtime.InteropServices;
21 namespace System.Data.SqlClient {
22 public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
26 SqlParameterCollection container = null;
28 ParameterDirection direction = ParameterDirection.Input;
30 bool isSizeSet = false;
31 bool isTypeSet = false;
40 DataRowVersion sourceVersion;
47 public SqlParameter ()
48 : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
52 public SqlParameter (string parameterName, object value)
54 this.parameterName = parameterName;
55 this.objValue = value;
56 this.sourceVersion = DataRowVersion.Current;
60 public SqlParameter (string parameterName, SqlDbType dbType)
61 : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
65 public SqlParameter (string parameterName, SqlDbType dbType, int size)
66 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
70 public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn)
71 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
75 [EditorBrowsable (EditorBrowsableState.Advanced)]
76 public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
82 ParameterName = parameterName;
83 Direction = direction;
84 IsNullable = isNullable;
85 Precision = precision;
87 SourceColumn = sourceColumn;
88 SourceVersion = sourceVersion;
91 // This constructor is used internally to construct a
92 // SqlParameter. The value array comes from sp_procedure_params_rowset.
93 // This is in SqlCommand.DeriveParameters.
94 internal SqlParameter (object[] dbValues)
98 direction = ParameterDirection.Input;
100 parameterName = (string) dbValues[3];
102 switch ((short) dbValues[5]) {
104 direction = ParameterDirection.Input;
107 direction = ParameterDirection.Output;
110 direction = ParameterDirection.InputOutput;
113 direction = ParameterDirection.ReturnValue;
117 isNullable = (bool) dbValues[8];
119 if (dbValues[12] != null)
120 precision = (byte) ((short) dbValues[12]);
121 if (dbValues[13] != null)
122 scale = (byte) ((short) dbValues[13]);
124 SetDbTypeName ((string) dbValues[16]);
127 #endregion // Constructors
131 // Used to ensure that only one collection can contain this
133 internal SqlParameterCollection Container {
134 get { return container; }
135 set { container = value; }
139 [DataCategory ("Data")]
140 [DataSysDescription ("The parameter generic type.")]
141 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
142 [RefreshProperties (RefreshProperties.All)]
143 public DbType DbType {
144 get { return dbType; }
151 [DataCategory ("Data")]
152 [DataSysDescription ("Input, output, or bidirectional parameter.")]
153 [DefaultValue (ParameterDirection.Input)]
154 public ParameterDirection Direction {
155 get { return direction; }
156 set { direction = value; }
159 string IDataParameter.ParameterName {
160 get { return parameterName; }
161 set { parameterName = value; }
165 [DataSysDescription ("a design-time property used for strongly typed code-generation.")]
166 [DefaultValue (false)]
168 [EditorBrowsable (EditorBrowsableState.Advanced)]
169 public bool IsNullable {
170 get { return isNullable; }
171 set { isNullable = value; }
175 [DataCategory ("Data")]
176 [DataSysDescription ("Offset in variable length data types.")]
179 get { return offset; }
180 set { offset = value; }
183 [DataSysDescription ("Name of the parameter, like '@p1'")]
185 public string ParameterName {
186 get { return parameterName; }
187 set { parameterName = value; }
190 [DataCategory ("Data")]
191 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
193 public byte Precision {
194 get { return precision; }
195 set { precision = value; }
198 [DataCategory ("Data")]
199 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
202 get { return scale; }
203 set { scale = value; }
206 [DataCategory ("Data")]
207 [DataSysDescription ("Size of variable length datatypes (strings & arrays).")]
217 [DataCategory ("Data")]
218 [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.")]
220 public string SourceColumn {
221 get { return sourceColumn; }
222 set { sourceColumn = value; }
225 [DataCategory ("Data")]
226 [DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
227 [DefaultValue (DataRowVersion.Current)]
228 public DataRowVersion SourceVersion {
229 get { return sourceVersion; }
230 set { sourceVersion = value; }
233 [DataCategory ("Data")]
234 [DataSysDescription ("The parameter native type.")]
235 [DefaultValue (SqlDbType.NVarChar)]
236 [RefreshProperties (RefreshProperties.All)]
237 public SqlDbType SqlDbType {
238 get { return sqlDbType; }
240 SetSqlDbType (value);
245 [DataCategory ("Data")]
246 [DataSysDescription ("Value of the parameter.")]
247 [DefaultValue (null)]
248 public object Value {
249 get { return objValue; }
252 InferSqlType (value);
257 #endregion // Properties
261 object ICloneable.Clone ()
263 return new SqlParameter (ParameterName, SqlDbType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
266 // If the value is set without the DbType/SqlDbType being set, then we
267 // infer type information.
268 private void InferSqlType (object value)
270 Type type = value.GetType ();
272 string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
274 switch (type.FullName) {
276 SetSqlDbType (SqlDbType.BigInt);
278 case "System.Boolean":
279 SetSqlDbType (SqlDbType.Bit);
281 case "System.String":
282 SetSqlDbType (SqlDbType.NVarChar);
284 case "System.DateTime":
285 SetSqlDbType (SqlDbType.DateTime);
287 case "System.Decimal":
288 SetSqlDbType (SqlDbType.Decimal);
290 case "System.Double":
291 SetSqlDbType (SqlDbType.Float);
293 case "System.Byte[]":
294 SetSqlDbType (SqlDbType.VarBinary);
297 SetSqlDbType (SqlDbType.TinyInt);
300 SetSqlDbType (SqlDbType.Int);
302 case "System.Single":
303 SetSqlDbType (SqlDbType.Real);
306 SetSqlDbType (SqlDbType.SmallInt);
309 SetSqlDbType (SqlDbType.UniqueIdentifier);
311 case "System.Object":
312 SetSqlDbType (SqlDbType.Variant);
315 throw new ArgumentException (exception);
319 internal string Prepare (string name)
321 StringBuilder result = new StringBuilder ();
322 result.Append (name);
324 result.Append (typeName);
327 case SqlDbType.VarBinary :
328 case SqlDbType.NVarChar :
329 case SqlDbType.VarChar :
330 if (!isSizeSet || size == 0)
331 throw new InvalidOperationException ("All variable length parameters must have an explicitly set non-zero size.");
332 result.Append (String.Format ("({0})", size));
334 case SqlDbType.NChar :
335 case SqlDbType.Char :
336 case SqlDbType.Binary :
338 result.Append (String.Format ("({0})", size));
340 case SqlDbType.Decimal :
341 result.Append (String.Format ("({0},{1})", precision, scale));
347 return result.ToString ();
350 // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
351 // string representation of the type name. If the DbType is not convertible
352 // to an SqlDbType, throw an exception.
353 private void SetDbType (DbType type)
355 string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
358 case DbType.AnsiString:
359 typeName = "varchar";
360 sqlDbType = SqlDbType.VarChar;
362 case DbType.AnsiStringFixedLength:
364 sqlDbType = SqlDbType.Char;
367 typeName = "varbinary";
368 sqlDbType = SqlDbType.VarBinary;
372 sqlDbType = SqlDbType.Bit;
375 typeName = "tinyint";
376 sqlDbType = SqlDbType.TinyInt;
378 case DbType.Currency:
379 sqlDbType = SqlDbType.Money;
383 case DbType.DateTime:
384 typeName = "datetime";
385 sqlDbType = SqlDbType.DateTime;
388 typeName = "decimal";
389 sqlDbType = SqlDbType.Decimal;
393 sqlDbType = SqlDbType.Float;
396 typeName = "uniqueidentifier";
397 sqlDbType = SqlDbType.UniqueIdentifier;
400 typeName = "smallint";
401 sqlDbType = SqlDbType.SmallInt;
405 sqlDbType = SqlDbType.Int;
409 sqlDbType = SqlDbType.BigInt;
412 typeName = "sql_variant";
413 sqlDbType = SqlDbType.Variant;
417 sqlDbType = SqlDbType.Real;
420 typeName = "nvarchar";
421 sqlDbType = SqlDbType.NVarChar;
423 case DbType.StringFixedLength:
425 sqlDbType = SqlDbType.NChar;
428 typeName = "datetime";
429 sqlDbType = SqlDbType.DateTime;
432 throw new ArgumentException (exception);
437 // Used by internal constructor which has a SQL Server typename
438 private void SetDbTypeName (string dbTypeName)
440 switch (dbTypeName.ToLower ()) {
442 SqlDbType = SqlDbType.BigInt;
445 SqlDbType = SqlDbType.Binary;
448 SqlDbType = SqlDbType.Bit;
451 SqlDbType = SqlDbType.Char;
454 SqlDbType = SqlDbType.DateTime;
457 SqlDbType = SqlDbType.Decimal;
460 SqlDbType = SqlDbType.Float;
463 SqlDbType = SqlDbType.Image;
466 SqlDbType = SqlDbType.Int;
469 SqlDbType = SqlDbType.Money;
472 SqlDbType = SqlDbType.NChar;
475 SqlDbType = SqlDbType.NText;
478 SqlDbType = SqlDbType.NVarChar;
481 SqlDbType = SqlDbType.Real;
483 case "smalldatetime":
484 SqlDbType = SqlDbType.SmallDateTime;
487 SqlDbType = SqlDbType.SmallInt;
490 SqlDbType = SqlDbType.SmallMoney;
493 SqlDbType = SqlDbType.Text;
496 SqlDbType = SqlDbType.Timestamp;
499 SqlDbType = SqlDbType.TinyInt;
501 case "uniqueidentifier":
502 SqlDbType = SqlDbType.UniqueIdentifier;
505 SqlDbType = SqlDbType.VarBinary;
508 SqlDbType = SqlDbType.VarChar;
511 SqlDbType = SqlDbType.Variant;
516 // When the SqlDbType is set, we also set the DbType, as well as the SQL Server
517 // string representation of the type name. If the SqlDbType is not convertible
518 // to a DbType, throw an exception.
519 private void SetSqlDbType (SqlDbType type)
521 string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
524 case SqlDbType.BigInt:
526 dbType = DbType.Int64;
528 case SqlDbType.Binary:
530 dbType = DbType.Binary;
532 case SqlDbType.Timestamp:
533 typeName = "timestamp";
534 dbType = DbType.Binary;
536 case SqlDbType.VarBinary:
537 typeName = "varbinary";
538 dbType = DbType.Binary;
542 dbType = DbType.Boolean;
546 dbType = DbType.AnsiStringFixedLength;
548 case SqlDbType.DateTime:
549 typeName = "datetime";
550 dbType = DbType.DateTime;
552 case SqlDbType.SmallDateTime:
553 typeName = "smalldatetime";
554 dbType = DbType.DateTime;
556 case SqlDbType.Decimal:
557 typeName = "decimal";
558 dbType = DbType.Decimal;
560 case SqlDbType.Float:
562 dbType = DbType.Double;
564 case SqlDbType.Image:
566 dbType = DbType.Binary;
570 dbType = DbType.Int32;
572 case SqlDbType.Money:
574 dbType = DbType.Currency;
576 case SqlDbType.SmallMoney:
577 typeName = "smallmoney";
578 dbType = DbType.Currency;
580 case SqlDbType.NChar:
582 dbType = DbType.StringFixedLength;
584 case SqlDbType.NText:
586 dbType = DbType.String;
588 case SqlDbType.NVarChar:
589 typeName = "nvarchar";
590 dbType = DbType.String;
594 dbType = DbType.Single;
596 case SqlDbType.SmallInt:
597 typeName = "smallint";
598 dbType = DbType.Int16;
602 dbType = DbType.AnsiString;
604 case SqlDbType.VarChar:
605 typeName = "varchar";
606 dbType = DbType.AnsiString;
608 case SqlDbType.TinyInt:
609 typeName = "tinyint";
610 dbType = DbType.Byte;
612 case SqlDbType.UniqueIdentifier:
613 typeName = "uniqueidentifier";
614 dbType = DbType.Guid;
616 case SqlDbType.Variant:
617 typeName = "sql_variant";
618 dbType = DbType.Object;
621 throw new ArgumentException (exception);
626 public override string ToString()
628 return parameterName;
631 #endregion // Methods