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)
8 // Diego Caravana (diego@toth.it)
9 // Umadevi S (sumadevi@novell.com)
11 // (C) Ximian, Inc. 2002
12 // Copyright (C) Tim Coleman, 2002
16 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 using Mono.Data.Tds.Protocol;
41 using System.ComponentModel;
43 using System.Data.Common;
45 using System.Data.ProviderBase;
46 using System.Data.SqlTypes;
48 using System.Runtime.InteropServices;
51 namespace System.Data.SqlClient {
52 [TypeConverterAttribute (typeof (SqlParameterConverter))]
54 public sealed class SqlParameter : DbParameterBase, IDbDataParameter, IDataParameter, ICloneable
56 public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
61 TdsMetaParameter metaParameter;
63 SqlParameterCollection container = null;
65 ParameterDirection direction = ParameterDirection.Input;
67 bool isSizeSet = false;
68 bool isTypeSet = false;
72 DataRowVersion sourceVersion;
78 public SqlParameter ()
79 : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
83 public SqlParameter (string parameterName, object value)
85 metaParameter = new TdsMetaParameter (parameterName, value);
86 this.sourceVersion = DataRowVersion.Current;
90 public SqlParameter (string parameterName, SqlDbType dbType)
91 : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
95 public SqlParameter (string parameterName, SqlDbType dbType, int size)
96 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
100 public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn)
101 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
105 [EditorBrowsable (EditorBrowsableState.Advanced)]
106 public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
108 metaParameter = new TdsMetaParameter (parameterName, size, isNullable, precision, scale, value);
111 Direction = direction;
112 SourceColumn = sourceColumn;
113 SourceVersion = sourceVersion;
116 // This constructor is used internally to construct a
117 // SqlParameter. The value array comes from sp_procedure_params_rowset.
118 // This is in SqlCommand.DeriveParameters.
119 internal SqlParameter (object[] dbValues)
120 : this (dbValues [3].ToString (), String.Empty)
124 Direction = ParameterDirection.Input;
126 ParameterName = (string) dbValues[3];
128 switch ((short) dbValues[5]) {
130 Direction = ParameterDirection.Input;
133 Direction = ParameterDirection.Output;
136 Direction = ParameterDirection.InputOutput;
139 Direction = ParameterDirection.ReturnValue;
142 Direction = ParameterDirection.Input;
145 IsNullable = (dbValues [8] != null &&
146 dbValues [8] != DBNull.Value) ? (bool) dbValues [8] : false;
148 if (dbValues [12] != null && dbValues [12] != DBNull.Value)
149 Precision = (byte) ((short) dbValues [12]);
151 if (dbValues [13] != null && dbValues [13] != DBNull.Value)
152 Scale = (byte) ( (short) dbValues [13]);
154 SetDbTypeName ((string) dbValues [16]);
157 #endregion // Constructors
161 // Used to ensure that only one collection can contain this
163 internal SqlParameterCollection Container {
164 get { return container; }
165 set { container = value; }
170 [DataSysDescription ("The parameter generic type.")]
171 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
172 [RefreshProperties (RefreshProperties.All)]
174 [DataCategory ("Data")]
180 get { return dbType; }
187 [DataCategory ("Data")]
189 [DataSysDescription ("Input, output, or bidirectional parameter.")]
190 [DefaultValue (ParameterDirection.Input)]
193 [RefreshProperties (RefreshProperties.All)]
199 ParameterDirection Direction {
200 get { return direction; }
203 switch( direction ) {
204 case ParameterDirection.Output:
205 MetaParameter.Direction = TdsParameterDirection.Output;
207 case ParameterDirection.InputOutput:
208 MetaParameter.Direction = TdsParameterDirection.InputOutput;
210 case ParameterDirection.ReturnValue:
211 MetaParameter.Direction = TdsParameterDirection.ReturnValue;
217 internal TdsMetaParameter MetaParameter {
218 get { return metaParameter; }
221 string IDataParameter.ParameterName {
222 get { return metaParameter.ParameterName; }
223 set { metaParameter.ParameterName = value; }
228 [DataSysDescription ("a design-time property used for strongly typed code-generation.")]
229 [DefaultValue (false)]
231 [EditorBrowsable (EditorBrowsableState.Advanced)]
238 get { return metaParameter.IsNullable; }
239 set { metaParameter.IsNullable = value; }
243 [DataCategory ("Data")]
245 [DataSysDescription ("Offset in variable length data types.")]
249 [EditorBrowsable (EditorBrowsableState.Advanced)]
256 get { return offset; }
257 set { offset = value; }
261 [DataSysDescription ("Name of the parameter, like '@p1'")]
268 string ParameterName {
269 get { return metaParameter.ParameterName; }
270 set { metaParameter.ParameterName = value; }
273 [DataCategory ("Data")]
275 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
280 [EditorBrowsable (EditorBrowsableState.Never)]
287 get { return metaParameter.Precision; }
288 set { metaParameter.Precision = value; }
291 [DataCategory ("Data")]
293 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
298 [EditorBrowsable (EditorBrowsableState.Never)]
305 get { return metaParameter.Scale; }
306 set { metaParameter.Scale = value; }
309 [DataCategory ("Data")]
311 [DataSysDescription ("Size of variable length data types (strings & arrays).")]
319 get { return metaParameter.Size; }
320 set { metaParameter.Size = value; }
323 [DataCategory ("Data")]
325 [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.")]
332 string SourceColumn {
333 get { return sourceColumn; }
334 set { sourceColumn = value; }
337 [DataCategory ("Data")]
339 [DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
340 [DefaultValue (DataRowVersion.Current)]
346 DataRowVersion SourceVersion {
347 get { return sourceVersion; }
348 set { sourceVersion = value; }
351 [DataCategory ("Data")]
353 [DataSysDescription ("The parameter native type.")]
354 [DefaultValue (SqlDbType.NVarChar)]
356 [RefreshProperties (RefreshProperties.All)]
358 [DbProviderSpecificTypeProperty(true)]
360 public SqlDbType SqlDbType {
361 get { return sqlDbType; }
363 SetSqlDbType (value);
368 [DataCategory ("Data")]
370 [DataSysDescription ("Value of the parameter.")]
371 [DefaultValue (null)]
373 [TypeConverterAttribute (typeof (StringConverter))]
375 [RefreshProperties (RefreshProperties.All)]
382 get { return metaParameter.Value; }
385 InferSqlType (value);
386 metaParameter.Value = value;
391 // public SqlCompareOptions CompareInfo{
395 #endregion // Properties
399 object ICloneable.Clone ()
401 return new SqlParameter (ParameterName, SqlDbType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
404 // If the value is set without the DbType/SqlDbType being set, then we
405 // infer type information.
406 private void InferSqlType (object value)
408 Type type = value.GetType ();
410 string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
412 switch (type.FullName) {
414 SetSqlDbType (SqlDbType.BigInt);
416 case "System.Boolean":
417 SetSqlDbType (SqlDbType.Bit);
419 case "System.String":
420 SetSqlDbType (SqlDbType.NVarChar);
422 case "System.DateTime":
423 SetSqlDbType (SqlDbType.DateTime);
425 case "System.Decimal":
426 SetSqlDbType (SqlDbType.Decimal);
428 case "System.Double":
429 SetSqlDbType (SqlDbType.Float);
431 case "System.Byte[]":
432 SetSqlDbType (SqlDbType.VarBinary);
435 SetSqlDbType (SqlDbType.TinyInt);
438 SetSqlDbType (SqlDbType.Int);
440 case "System.Single":
441 SetSqlDbType (SqlDbType.Real);
444 SetSqlDbType (SqlDbType.SmallInt);
447 SetSqlDbType (SqlDbType.UniqueIdentifier);
449 case "System.Object":
450 SetSqlDbType (SqlDbType.Variant);
452 case "System.DBNull":
453 SetSqlDbType(SqlDbType.Variant); // variant can contain numeric,
454 //string,binary or data and also nul //values, so we can later resolve // it to correct type.
457 throw new ArgumentException (exception);
461 // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
462 // string representation of the type name. If the DbType is not convertible
463 // to an SqlDbType, throw an exception.
464 private void SetDbType (DbType type)
466 string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
469 case DbType.AnsiString:
470 MetaParameter.TypeName = "varchar";
471 sqlDbType = SqlDbType.VarChar;
473 case DbType.AnsiStringFixedLength:
474 MetaParameter.TypeName = "char";
475 sqlDbType = SqlDbType.Char;
478 MetaParameter.TypeName = "varbinary";
479 sqlDbType = SqlDbType.VarBinary;
482 MetaParameter.TypeName = "bit";
483 sqlDbType = SqlDbType.Bit;
486 MetaParameter.TypeName = "tinyint";
487 sqlDbType = SqlDbType.TinyInt;
489 case DbType.Currency:
490 sqlDbType = SqlDbType.Money;
491 MetaParameter.TypeName = "money";
494 case DbType.DateTime:
495 MetaParameter.TypeName = "datetime";
496 sqlDbType = SqlDbType.DateTime;
499 MetaParameter.TypeName = "decimal";
500 sqlDbType = SqlDbType.Decimal;
503 MetaParameter.TypeName = "float";
504 sqlDbType = SqlDbType.Float;
507 MetaParameter.TypeName = "uniqueidentifier";
508 sqlDbType = SqlDbType.UniqueIdentifier;
511 MetaParameter.TypeName = "smallint";
512 sqlDbType = SqlDbType.SmallInt;
515 MetaParameter.TypeName = "int";
516 sqlDbType = SqlDbType.Int;
519 MetaParameter.TypeName = "bigint";
520 sqlDbType = SqlDbType.BigInt;
523 MetaParameter.TypeName = "sql_variant";
524 sqlDbType = SqlDbType.Variant;
527 MetaParameter.TypeName = "real";
528 sqlDbType = SqlDbType.Real;
531 MetaParameter.TypeName = "nvarchar";
532 sqlDbType = SqlDbType.NVarChar;
534 case DbType.StringFixedLength:
535 MetaParameter.TypeName = "nchar";
536 sqlDbType = SqlDbType.NChar;
539 MetaParameter.TypeName = "datetime";
540 sqlDbType = SqlDbType.DateTime;
543 throw new ArgumentException (exception);
548 // Used by internal constructor which has a SQL Server typename
549 private void SetDbTypeName (string dbTypeName)
551 switch (dbTypeName.ToLower ()) {
553 SqlDbType = SqlDbType.BigInt;
556 SqlDbType = SqlDbType.Binary;
559 SqlDbType = SqlDbType.Bit;
562 SqlDbType = SqlDbType.Char;
565 SqlDbType = SqlDbType.DateTime;
568 SqlDbType = SqlDbType.Decimal;
571 SqlDbType = SqlDbType.Float;
574 SqlDbType = SqlDbType.Image;
577 SqlDbType = SqlDbType.Int;
580 SqlDbType = SqlDbType.Money;
583 SqlDbType = SqlDbType.NChar;
586 SqlDbType = SqlDbType.NText;
589 SqlDbType = SqlDbType.NVarChar;
592 SqlDbType = SqlDbType.Real;
594 case "smalldatetime":
595 SqlDbType = SqlDbType.SmallDateTime;
598 SqlDbType = SqlDbType.SmallInt;
601 SqlDbType = SqlDbType.SmallMoney;
604 SqlDbType = SqlDbType.Text;
607 SqlDbType = SqlDbType.Timestamp;
610 SqlDbType = SqlDbType.TinyInt;
612 case "uniqueidentifier":
613 SqlDbType = SqlDbType.UniqueIdentifier;
616 SqlDbType = SqlDbType.VarBinary;
619 SqlDbType = SqlDbType.VarChar;
622 SqlDbType = SqlDbType.Variant;
627 // When the SqlDbType is set, we also set the DbType, as well as the SQL Server
628 // string representation of the type name. If the SqlDbType is not convertible
629 // to a DbType, throw an exception.
630 private void SetSqlDbType (SqlDbType type)
632 string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
635 case SqlDbType.BigInt:
636 MetaParameter.TypeName = "bigint";
637 dbType = DbType.Int64;
639 case SqlDbType.Binary:
640 MetaParameter.TypeName = "binary";
641 dbType = DbType.Binary;
643 case SqlDbType.Timestamp:
644 MetaParameter.TypeName = "timestamp";
645 dbType = DbType.Binary;
647 case SqlDbType.VarBinary:
648 MetaParameter.TypeName = "varbinary";
649 dbType = DbType.Binary;
652 MetaParameter.TypeName = "bit";
653 dbType = DbType.Boolean;
656 MetaParameter.TypeName = "char";
657 dbType = DbType.AnsiStringFixedLength;
659 case SqlDbType.DateTime:
660 MetaParameter.TypeName = "datetime";
661 dbType = DbType.DateTime;
663 case SqlDbType.SmallDateTime:
664 MetaParameter.TypeName = "smalldatetime";
665 dbType = DbType.DateTime;
667 case SqlDbType.Decimal:
668 MetaParameter.TypeName = "decimal";
669 dbType = DbType.Decimal;
671 case SqlDbType.Float:
672 MetaParameter.TypeName = "float";
673 dbType = DbType.Double;
675 case SqlDbType.Image:
676 MetaParameter.TypeName = "image";
677 dbType = DbType.Binary;
680 MetaParameter.TypeName = "int";
681 dbType = DbType.Int32;
683 case SqlDbType.Money:
684 MetaParameter.TypeName = "money";
685 dbType = DbType.Currency;
687 case SqlDbType.SmallMoney:
688 MetaParameter.TypeName = "smallmoney";
689 dbType = DbType.Currency;
691 case SqlDbType.NChar:
692 MetaParameter.TypeName = "nchar";
693 dbType = DbType.StringFixedLength;
695 case SqlDbType.NText:
696 MetaParameter.TypeName = "ntext";
697 dbType = DbType.String;
699 case SqlDbType.NVarChar:
700 MetaParameter.TypeName = "nvarchar";
701 dbType = DbType.String;
704 MetaParameter.TypeName = "real";
705 dbType = DbType.Single;
707 case SqlDbType.SmallInt:
708 MetaParameter.TypeName = "smallint";
709 dbType = DbType.Int16;
712 MetaParameter.TypeName = "text";
713 dbType = DbType.AnsiString;
715 case SqlDbType.VarChar:
716 MetaParameter.TypeName = "varchar";
717 dbType = DbType.AnsiString;
719 case SqlDbType.TinyInt:
720 MetaParameter.TypeName = "tinyint";
721 dbType = DbType.Byte;
723 case SqlDbType.UniqueIdentifier:
724 MetaParameter.TypeName = "uniqueidentifier";
725 dbType = DbType.Guid;
727 case SqlDbType.Variant:
728 MetaParameter.TypeName = "sql_variant";
729 dbType = DbType.Object;
732 throw new ArgumentException (exception);
737 public override string ToString()
739 return ParameterName;
744 public override void CopyTo (DbParameter param)
746 throw new NotImplementedException ();
750 public override void ResetDbType ()
752 throw new NotImplementedException ();
756 #endregion // Methods