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)
10 // (C) Ximian, Inc. 2002
11 // Copyright (C) Tim Coleman, 2002
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 using Mono.Data.Tds.Protocol;
40 using System.ComponentModel;
42 using System.Data.Common;
44 using System.Data.ProviderBase;
46 using System.Runtime.InteropServices;
49 namespace System.Data.SqlClient {
50 [TypeConverterAttribute (typeof (SqlParameterConverter))]
52 public sealed class SqlParameter : DbParameterBase, IDbDataParameter, IDataParameter, ICloneable
54 public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
59 TdsMetaParameter metaParameter;
61 SqlParameterCollection container = null;
63 ParameterDirection direction = ParameterDirection.Input;
65 bool isSizeSet = false;
66 bool isTypeSet = false;
70 DataRowVersion sourceVersion;
76 public SqlParameter ()
77 : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
81 public SqlParameter (string parameterName, object value)
83 metaParameter = new TdsMetaParameter (parameterName, value);
84 this.sourceVersion = DataRowVersion.Current;
88 public SqlParameter (string parameterName, SqlDbType dbType)
89 : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
93 public SqlParameter (string parameterName, SqlDbType dbType, int size)
94 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
98 public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn)
99 : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
103 [EditorBrowsable (EditorBrowsableState.Advanced)]
104 public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
106 metaParameter = new TdsMetaParameter (parameterName, size, isNullable, precision, scale, value);
109 Direction = direction;
110 SourceColumn = sourceColumn;
111 SourceVersion = sourceVersion;
114 // This constructor is used internally to construct a
115 // SqlParameter. The value array comes from sp_procedure_params_rowset.
116 // This is in SqlCommand.DeriveParameters.
117 internal SqlParameter (object[] dbValues)
121 Direction = ParameterDirection.Input;
123 ParameterName = (string) dbValues[3];
125 switch ((short) dbValues[5]) {
127 Direction = ParameterDirection.Input;
130 Direction = ParameterDirection.Output;
133 Direction = ParameterDirection.InputOutput;
136 Direction = ParameterDirection.ReturnValue;
140 IsNullable = (bool) dbValues[8];
142 if (dbValues[12] != null)
143 Precision = (byte) ((short) dbValues[12]);
144 if (dbValues[13] != null)
145 Scale = (byte) ((short) dbValues[13]);
147 SetDbTypeName ((string) dbValues[16]);
150 #endregion // Constructors
154 // Used to ensure that only one collection can contain this
156 internal SqlParameterCollection Container {
157 get { return container; }
158 set { container = value; }
162 [DataCategory ("Data")]
163 [DataSysDescription ("The parameter generic type.")]
164 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
165 [RefreshProperties (RefreshProperties.All)]
171 get { return dbType; }
178 [DataCategory ("Data")]
179 [DataSysDescription ("Input, output, or bidirectional parameter.")]
180 [DefaultValue (ParameterDirection.Input)]
185 ParameterDirection Direction {
186 get { return direction; }
189 switch( direction ) {
190 case ParameterDirection.Output:
191 MetaParameter.Direction = TdsParameterDirection.Output;
193 case ParameterDirection.InputOutput:
194 MetaParameter.Direction = TdsParameterDirection.InputOutput;
196 case ParameterDirection.ReturnValue:
197 MetaParameter.Direction = TdsParameterDirection.ReturnValue;
203 internal TdsMetaParameter MetaParameter {
204 get { return metaParameter; }
207 string IDataParameter.ParameterName {
208 get { return metaParameter.ParameterName; }
209 set { metaParameter.ParameterName = value; }
213 [DataSysDescription ("a design-time property used for strongly typed code-generation.")]
214 [DefaultValue (false)]
216 [EditorBrowsable (EditorBrowsableState.Advanced)]
222 get { return metaParameter.IsNullable; }
223 set { metaParameter.IsNullable = value; }
227 [DataCategory ("Data")]
228 [DataSysDescription ("Offset in variable length data types.")]
235 get { return offset; }
236 set { offset = value; }
239 [DataSysDescription ("Name of the parameter, like '@p1'")]
245 string ParameterName {
246 get { return metaParameter.ParameterName; }
247 set { metaParameter.ParameterName = value; }
250 [DataCategory ("Data")]
251 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
258 get { return metaParameter.Precision; }
259 set { metaParameter.Precision = value; }
262 [DataCategory ("Data")]
263 [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
270 get { return metaParameter.Scale; }
271 set { metaParameter.Scale = value; }
274 [DataCategory ("Data")]
275 [DataSysDescription ("Size of variable length datatypes (strings & arrays).")]
282 get { return metaParameter.Size; }
283 set { metaParameter.Size = value; }
286 [DataCategory ("Data")]
287 [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.")]
293 string SourceColumn {
294 get { return sourceColumn; }
295 set { sourceColumn = value; }
298 [DataCategory ("Data")]
299 [DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
300 [DefaultValue (DataRowVersion.Current)]
305 DataRowVersion SourceVersion {
306 get { return sourceVersion; }
307 set { sourceVersion = value; }
310 [DataCategory ("Data")]
311 [DataSysDescription ("The parameter native type.")]
312 [DefaultValue (SqlDbType.NVarChar)]
313 [RefreshProperties (RefreshProperties.All)]
314 public SqlDbType SqlDbType {
315 get { return sqlDbType; }
317 SetSqlDbType (value);
322 [DataCategory ("Data")]
323 [DataSysDescription ("Value of the parameter.")]
324 [DefaultValue (null)]
325 [TypeConverterAttribute (typeof (StringConverter))]
331 get { return metaParameter.Value; }
334 InferSqlType (value);
335 metaParameter.Value = value;
339 #endregion // Properties
343 object ICloneable.Clone ()
345 return new SqlParameter (ParameterName, SqlDbType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
348 // If the value is set without the DbType/SqlDbType being set, then we
349 // infer type information.
350 private void InferSqlType (object value)
352 Type type = value.GetType ();
354 string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
356 switch (type.FullName) {
358 SetSqlDbType (SqlDbType.BigInt);
360 case "System.Boolean":
361 SetSqlDbType (SqlDbType.Bit);
363 case "System.String":
364 SetSqlDbType (SqlDbType.NVarChar);
366 case "System.DateTime":
367 SetSqlDbType (SqlDbType.DateTime);
369 case "System.Decimal":
370 SetSqlDbType (SqlDbType.Decimal);
372 case "System.Double":
373 SetSqlDbType (SqlDbType.Float);
375 case "System.Byte[]":
376 SetSqlDbType (SqlDbType.VarBinary);
379 SetSqlDbType (SqlDbType.TinyInt);
382 SetSqlDbType (SqlDbType.Int);
384 case "System.Single":
385 SetSqlDbType (SqlDbType.Real);
388 SetSqlDbType (SqlDbType.SmallInt);
391 SetSqlDbType (SqlDbType.UniqueIdentifier);
393 case "System.Object":
394 SetSqlDbType (SqlDbType.Variant);
397 throw new ArgumentException (exception);
401 // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
402 // string representation of the type name. If the DbType is not convertible
403 // to an SqlDbType, throw an exception.
404 private void SetDbType (DbType type)
406 string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
409 case DbType.AnsiString:
410 MetaParameter.TypeName = "varchar";
411 sqlDbType = SqlDbType.VarChar;
413 case DbType.AnsiStringFixedLength:
414 MetaParameter.TypeName = "char";
415 sqlDbType = SqlDbType.Char;
418 MetaParameter.TypeName = "varbinary";
419 sqlDbType = SqlDbType.VarBinary;
422 MetaParameter.TypeName = "bit";
423 sqlDbType = SqlDbType.Bit;
426 MetaParameter.TypeName = "tinyint";
427 sqlDbType = SqlDbType.TinyInt;
429 case DbType.Currency:
430 sqlDbType = SqlDbType.Money;
431 MetaParameter.TypeName = "money";
434 case DbType.DateTime:
435 MetaParameter.TypeName = "datetime";
436 sqlDbType = SqlDbType.DateTime;
439 MetaParameter.TypeName = "decimal";
440 sqlDbType = SqlDbType.Decimal;
443 MetaParameter.TypeName = "float";
444 sqlDbType = SqlDbType.Float;
447 MetaParameter.TypeName = "uniqueidentifier";
448 sqlDbType = SqlDbType.UniqueIdentifier;
451 MetaParameter.TypeName = "smallint";
452 sqlDbType = SqlDbType.SmallInt;
455 MetaParameter.TypeName = "int";
456 sqlDbType = SqlDbType.Int;
459 MetaParameter.TypeName = "bigint";
460 sqlDbType = SqlDbType.BigInt;
463 MetaParameter.TypeName = "sql_variant";
464 sqlDbType = SqlDbType.Variant;
467 MetaParameter.TypeName = "real";
468 sqlDbType = SqlDbType.Real;
471 MetaParameter.TypeName = "nvarchar";
472 sqlDbType = SqlDbType.NVarChar;
474 case DbType.StringFixedLength:
475 MetaParameter.TypeName = "nchar";
476 sqlDbType = SqlDbType.NChar;
479 MetaParameter.TypeName = "datetime";
480 sqlDbType = SqlDbType.DateTime;
483 throw new ArgumentException (exception);
488 // Used by internal constructor which has a SQL Server typename
489 private void SetDbTypeName (string dbTypeName)
491 switch (dbTypeName.ToLower ()) {
493 SqlDbType = SqlDbType.BigInt;
496 SqlDbType = SqlDbType.Binary;
499 SqlDbType = SqlDbType.Bit;
502 SqlDbType = SqlDbType.Char;
505 SqlDbType = SqlDbType.DateTime;
508 SqlDbType = SqlDbType.Decimal;
511 SqlDbType = SqlDbType.Float;
514 SqlDbType = SqlDbType.Image;
517 SqlDbType = SqlDbType.Int;
520 SqlDbType = SqlDbType.Money;
523 SqlDbType = SqlDbType.NChar;
526 SqlDbType = SqlDbType.NText;
529 SqlDbType = SqlDbType.NVarChar;
532 SqlDbType = SqlDbType.Real;
534 case "smalldatetime":
535 SqlDbType = SqlDbType.SmallDateTime;
538 SqlDbType = SqlDbType.SmallInt;
541 SqlDbType = SqlDbType.SmallMoney;
544 SqlDbType = SqlDbType.Text;
547 SqlDbType = SqlDbType.Timestamp;
550 SqlDbType = SqlDbType.TinyInt;
552 case "uniqueidentifier":
553 SqlDbType = SqlDbType.UniqueIdentifier;
556 SqlDbType = SqlDbType.VarBinary;
559 SqlDbType = SqlDbType.VarChar;
562 SqlDbType = SqlDbType.Variant;
567 // When the SqlDbType is set, we also set the DbType, as well as the SQL Server
568 // string representation of the type name. If the SqlDbType is not convertible
569 // to a DbType, throw an exception.
570 private void SetSqlDbType (SqlDbType type)
572 string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
575 case SqlDbType.BigInt:
576 MetaParameter.TypeName = "bigint";
577 dbType = DbType.Int64;
579 case SqlDbType.Binary:
580 MetaParameter.TypeName = "binary";
581 dbType = DbType.Binary;
583 case SqlDbType.Timestamp:
584 MetaParameter.TypeName = "timestamp";
585 dbType = DbType.Binary;
587 case SqlDbType.VarBinary:
588 MetaParameter.TypeName = "varbinary";
589 dbType = DbType.Binary;
592 MetaParameter.TypeName = "bit";
593 dbType = DbType.Boolean;
596 MetaParameter.TypeName = "char";
597 dbType = DbType.AnsiStringFixedLength;
599 case SqlDbType.DateTime:
600 MetaParameter.TypeName = "datetime";
601 dbType = DbType.DateTime;
603 case SqlDbType.SmallDateTime:
604 MetaParameter.TypeName = "smalldatetime";
605 dbType = DbType.DateTime;
607 case SqlDbType.Decimal:
608 MetaParameter.TypeName = "decimal";
609 dbType = DbType.Decimal;
611 case SqlDbType.Float:
612 MetaParameter.TypeName = "float";
613 dbType = DbType.Double;
615 case SqlDbType.Image:
616 MetaParameter.TypeName = "image";
617 dbType = DbType.Binary;
620 MetaParameter.TypeName = "int";
621 dbType = DbType.Int32;
623 case SqlDbType.Money:
624 MetaParameter.TypeName = "money";
625 dbType = DbType.Currency;
627 case SqlDbType.SmallMoney:
628 MetaParameter.TypeName = "smallmoney";
629 dbType = DbType.Currency;
631 case SqlDbType.NChar:
632 MetaParameter.TypeName = "nchar";
633 dbType = DbType.StringFixedLength;
635 case SqlDbType.NText:
636 MetaParameter.TypeName = "ntext";
637 dbType = DbType.String;
639 case SqlDbType.NVarChar:
640 MetaParameter.TypeName = "nvarchar";
641 dbType = DbType.String;
644 MetaParameter.TypeName = "real";
645 dbType = DbType.Single;
647 case SqlDbType.SmallInt:
648 MetaParameter.TypeName = "smallint";
649 dbType = DbType.Int16;
652 MetaParameter.TypeName = "text";
653 dbType = DbType.AnsiString;
655 case SqlDbType.VarChar:
656 MetaParameter.TypeName = "varchar";
657 dbType = DbType.AnsiString;
659 case SqlDbType.TinyInt:
660 MetaParameter.TypeName = "tinyint";
661 dbType = DbType.Byte;
663 case SqlDbType.UniqueIdentifier:
664 MetaParameter.TypeName = "uniqueidentifier";
665 dbType = DbType.Guid;
667 case SqlDbType.Variant:
668 MetaParameter.TypeName = "sql_variant";
669 dbType = DbType.Object;
672 throw new ArgumentException (exception);
677 public override string ToString()
679 return ParameterName;
684 public override void CopyTo (DbParameter param)
686 throw new NotImplementedException ();
690 public override void ResetDbType ()
692 throw new NotImplementedException ();
696 #endregion // Methods