[runtime] Updates comments.
[mono.git] / mcs / class / System.Data / System.Data.SqlClient / SqlParameter.cs
1 //
2 // System.Data.SqlClient.SqlParameter.cs
3 //
4 // Author:
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)
10 //   Amit Biswas (amit@amitbiswas.com)
11 //   Veerapuram Varadhan (vvaradhan@novell.com)
12 //
13 // (C) Ximian, Inc. 2002
14 // Copyright (C) Tim Coleman, 2002
15 //
16
17 //
18 // Copyright (C) 2004, 2008, 2009 Novell, Inc (http://www.novell.com)
19 //
20 // Permission is hereby granted, free of charge, to any person obtaining
21 // a copy of this software and associated documentation files (the
22 // "Software"), to deal in the Software without restriction, including
23 // without limitation the rights to use, copy, modify, merge, publish,
24 // distribute, sublicense, and/or sell copies of the Software, and to
25 // permit persons to whom the Software is furnished to do so, subject to
26 // the following conditions:
27 // 
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
30 // 
31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 //
39
40 using Mono.Data.Tds;
41 using Mono.Data.Tds.Protocol;
42 using System;
43 using System.Collections;
44 using System.ComponentModel;
45 using System.Data;
46 using System.Data.Common;
47 using System.Data.SqlTypes;
48 using System.Globalization;
49 using System.Runtime.InteropServices;
50 using System.Text;
51 using System.Xml;
52
53 namespace System.Data.SqlClient {
54         [TypeConverterAttribute ("System.Data.SqlClient.SqlParameter+SqlParameterConverter, " + Consts.AssemblySystem_Data)]
55         public sealed class SqlParameter : DbParameter, IDbDataParameter, IDataParameter, ICloneable
56         {
57                 #region Fields
58
59                 TdsMetaParameter metaParameter;
60
61                 SqlParameterCollection container;
62                 DbType dbType;
63                 ParameterDirection direction = ParameterDirection.Input;
64                 bool isTypeSet;
65                 int offset;
66                 SqlDbType sqlDbType;
67                 string sourceColumn;
68                 DataRowVersion sourceVersion;
69                 SqlCompareOptions compareInfo;
70                 int localeId;
71                 Type sqlType;
72                 bool typeChanged;
73                 bool sourceColumnNullMapping;
74                 string xmlSchemaCollectionDatabase = String.Empty;
75                 string xmlSchemaCollectionOwningSchema = String.Empty;
76                 string xmlSchemaCollectionName = String.Empty;
77
78                 static Hashtable type_mapping;
79
80                 #endregion // Fields
81
82                 #region Constructors
83
84                 
85                 static SqlParameter ()
86                 {
87                         if (DbTypeMapping == null)
88                                 DbTypeMapping = new Hashtable ();
89                         
90                         DbTypeMapping.Add (SqlDbType.BigInt, typeof (long));
91                         DbTypeMapping.Add (SqlDbType.Bit, typeof (bool));
92                         DbTypeMapping.Add (SqlDbType.Char, typeof (string));
93                         DbTypeMapping.Add (SqlDbType.NChar, typeof (string));
94                         DbTypeMapping.Add (SqlDbType.Text, typeof (string));
95                         DbTypeMapping.Add (SqlDbType.NText, typeof (string));
96                         DbTypeMapping.Add (SqlDbType.VarChar, typeof (string));
97                         DbTypeMapping.Add (SqlDbType.NVarChar, typeof (string));
98                         DbTypeMapping.Add (SqlDbType.SmallDateTime, typeof (DateTime));
99                         DbTypeMapping.Add (SqlDbType.DateTime, typeof (DateTime));
100                         DbTypeMapping.Add (SqlDbType.Decimal, typeof (decimal));
101                         DbTypeMapping.Add (SqlDbType.Float, typeof (double));
102                         DbTypeMapping.Add (SqlDbType.Binary, typeof (byte []));
103                         DbTypeMapping.Add (SqlDbType.Image, typeof (byte []));
104                         DbTypeMapping.Add (SqlDbType.Money, typeof (decimal));
105                         DbTypeMapping.Add (SqlDbType.SmallMoney, typeof (decimal));
106                         DbTypeMapping.Add (SqlDbType.VarBinary, typeof (byte []));
107                         DbTypeMapping.Add (SqlDbType.TinyInt, typeof (byte));
108                         DbTypeMapping.Add (SqlDbType.Int, typeof (int));
109                         DbTypeMapping.Add (SqlDbType.Real, typeof (float));
110                         DbTypeMapping.Add (SqlDbType.SmallInt, typeof (short));
111                         DbTypeMapping.Add (SqlDbType.UniqueIdentifier, typeof (Guid));
112                         DbTypeMapping.Add (SqlDbType.Variant, typeof (object));
113                         DbTypeMapping.Add (SqlDbType.Xml, typeof (string));
114
115                         type_mapping = new Hashtable ();
116
117                         type_mapping.Add (typeof (long), SqlDbType.BigInt);
118                         type_mapping.Add (typeof (SqlTypes.SqlInt64), SqlDbType.BigInt);
119
120                         type_mapping.Add (typeof (bool), SqlDbType.Bit);
121                         type_mapping.Add (typeof (SqlTypes.SqlBoolean), SqlDbType.Bit);
122
123                         type_mapping.Add (typeof (char), SqlDbType.NVarChar);
124                         type_mapping.Add (typeof (char []), SqlDbType.NVarChar);
125                         type_mapping.Add (typeof (SqlTypes.SqlChars), SqlDbType.NVarChar);
126
127                         type_mapping.Add (typeof (string), SqlDbType.NVarChar);
128                         type_mapping.Add (typeof (SqlTypes.SqlString), SqlDbType.NVarChar);
129
130                         type_mapping.Add (typeof (DateTime), SqlDbType.DateTime);
131                         type_mapping.Add (typeof (SqlTypes.SqlDateTime), SqlDbType.DateTime);
132
133                         type_mapping.Add (typeof (decimal), SqlDbType.Decimal);
134                         type_mapping.Add (typeof (SqlTypes.SqlDecimal), SqlDbType.Decimal);
135
136                         type_mapping.Add (typeof (double), SqlDbType.Float);
137                         type_mapping.Add (typeof (SqlTypes.SqlDouble), SqlDbType.Float);
138
139                         type_mapping.Add (typeof (byte []), SqlDbType.VarBinary);
140                         type_mapping.Add (typeof (SqlTypes.SqlBinary), SqlDbType.VarBinary);
141
142                         type_mapping.Add (typeof (SqlTypes.SqlBytes), SqlDbType.VarBinary);
143
144                         type_mapping.Add (typeof (byte), SqlDbType.TinyInt);
145                         type_mapping.Add (typeof (SqlTypes.SqlByte), SqlDbType.TinyInt);
146
147                         type_mapping.Add (typeof (int), SqlDbType.Int);
148                         type_mapping.Add (typeof (SqlTypes.SqlInt32), SqlDbType.Int);
149
150                         type_mapping.Add (typeof (float), SqlDbType.Real);
151                         type_mapping.Add (typeof (SqlTypes.SqlSingle), SqlDbType.Real);
152
153                         type_mapping.Add (typeof (short), SqlDbType.SmallInt);
154                         type_mapping.Add (typeof (SqlTypes.SqlInt16), SqlDbType.SmallInt);
155
156                         type_mapping.Add (typeof (Guid), SqlDbType.UniqueIdentifier);
157                         type_mapping.Add (typeof (SqlTypes.SqlGuid), SqlDbType.UniqueIdentifier);
158
159                         type_mapping.Add (typeof (SqlTypes.SqlMoney), SqlDbType.Money);
160
161                         type_mapping.Add (typeof (XmlReader), SqlDbType.Xml);
162                         type_mapping.Add (typeof (SqlTypes.SqlXml), SqlDbType.Xml);
163
164                         type_mapping.Add (typeof (object), SqlDbType.Variant);
165                 }
166                 
167                 public SqlParameter () 
168                         : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
169                 {
170                         isTypeSet = false;
171                 }
172
173                 public SqlParameter (string parameterName, object value)
174                 {
175                         if (parameterName == null)
176                                 parameterName = string.Empty;
177                         metaParameter = new TdsMetaParameter (parameterName, GetFrameworkValue);
178                         metaParameter.RawValue = value;
179                         InferSqlType (value);
180                         sourceVersion = DataRowVersion.Current;
181                 }
182                 
183                 public SqlParameter (string parameterName, SqlDbType dbType) 
184                         : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null)
185                 {
186                 }
187
188                 public SqlParameter (string parameterName, SqlDbType dbType, int size) 
189                         : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null)
190                 {
191                 }
192                 
193                 public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn) 
194                         : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
195                 {
196                 }
197                 
198                 [EditorBrowsable (EditorBrowsableState.Advanced)]
199                 public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value) 
200                 {
201                         if (parameterName == null)
202                                 parameterName = string.Empty;
203
204                         metaParameter = new TdsMetaParameter (parameterName, size, 
205                                                               isNullable, precision, 
206                                                               scale,
207                                                               GetFrameworkValue);
208                         metaParameter.RawValue =  value;
209                         if (dbType != SqlDbType.Variant) 
210                                 SqlDbType = dbType;
211                         Direction = direction;
212                         SourceColumn = sourceColumn;
213                         SourceVersion = sourceVersion;
214                 }
215
216                 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)
217                         : this (parameterName, dbType, size, direction, false, precision, scale, sourceColumn, sourceVersion, value)
218                 {
219                         XmlSchemaCollectionDatabase = xmlSchemaCollectionDatabase;
220                         XmlSchemaCollectionOwningSchema = xmlSchemaCollectionOwningSchema;
221                         XmlSchemaCollectionName = xmlSchemaCollectionName;
222                         SourceColumnNullMapping = sourceColumnNullMapping;
223                 }
224
225                 // This constructor is used internally to construct a
226                 // SqlParameter.  The value array comes from sp_procedure_params_rowset.
227                 // This is in SqlCommand.DeriveParameters.
228                 //
229                 // http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/900756fd-3980-48e3-ae59-a15d7fc15b4c/
230                 internal SqlParameter (object[] dbValues) 
231                         : this (dbValues [3].ToString (), (object) null)
232                 {
233                         ParameterName = (string) dbValues [3];
234
235                         switch ((short) dbValues [5]) {
236                         case 1:
237                                 Direction = ParameterDirection.Input;
238                                 break;
239                         case 2:
240                                 Direction = ParameterDirection.InputOutput;
241                                 break;
242                         case 3:
243                                 Direction = ParameterDirection.Output;
244                                 break;
245                         case 4:
246                                 Direction = ParameterDirection.ReturnValue;
247                                 break;
248                         default:
249                                 Direction = ParameterDirection.Input;
250                                 break;
251                         }
252
253                         SqlDbType = (SqlDbType) FrameworkDbTypeFromName ((string) dbValues [16]);
254
255                         if (MetaParameter.IsVariableSizeType) {
256                                 if (dbValues [10] != DBNull.Value)
257                                         Size = (int) dbValues [10];
258                         }
259
260                         if (SqlDbType == SqlDbType.Decimal) {
261                                 if (dbValues [12] != null && dbValues [12] != DBNull.Value)
262                                         Precision = (byte) ((short) dbValues [12]);
263                                 if (dbValues [13] != null && dbValues [13] != DBNull.Value)
264                                         Scale = (byte) ((short) dbValues [13]);
265                         }
266                 }
267
268                 #endregion // Constructors
269
270                 #region Properties
271
272                 // Used to ensure that only one collection can contain this
273                 // parameter
274                 internal SqlParameterCollection Container {
275                         get { return container; }
276                         set { container = value; }
277                 }
278
279                 internal void CheckIfInitialized ()
280                 {
281                         if (!isTypeSet)
282                                 throw new Exception ("all parameters to have an explicity set type");
283
284                         if (MetaParameter.IsVariableSizeType) {
285                                 if (SqlDbType == SqlDbType.Decimal && Precision == 0)
286                                         throw new Exception ("Parameter of type 'Decimal' have an explicitly set Precision and Scale");
287                                 else if (Size == 0)
288                                         throw new Exception ("all variable length parameters to have an explicitly set non-zero Size");
289                         }
290                 }
291         
292                 public override DbType DbType {
293                         get { return dbType; }
294                         set {
295                                 SetDbType (value);
296                                 typeChanged = true;
297                                 isTypeSet = true;
298                         }
299                 }
300
301                 [RefreshProperties (RefreshProperties.All)]
302                 public override
303                 ParameterDirection Direction {
304                         get { return direction; }
305                         set { 
306                                 direction = value; 
307                                 switch( direction ) {
308                                         case ParameterDirection.Output:
309                                                 MetaParameter.Direction = TdsParameterDirection.Output;
310                                                 break;
311                                         case ParameterDirection.InputOutput:
312                                                 MetaParameter.Direction = TdsParameterDirection.InputOutput;
313                                                 break;
314                                         case ParameterDirection.ReturnValue:
315                                                 MetaParameter.Direction = TdsParameterDirection.ReturnValue;
316                                                 break;
317                                 }
318                         }
319                 }
320
321                 internal TdsMetaParameter MetaParameter {
322                         get { return metaParameter; }
323                 }
324
325                 public override bool IsNullable {
326                         get { return metaParameter.IsNullable; }
327                         set { metaParameter.IsNullable = value; }
328                 }
329
330                 [Browsable (false)]
331                 [EditorBrowsable (EditorBrowsableState.Advanced)]
332                 public int Offset {
333                         get { return offset; }
334                         set { offset = value; }
335                 }
336         
337                 public override string ParameterName {
338                         get { return metaParameter.ParameterName; }
339                         set {
340                                 if (value == null)
341                                         value = string.Empty;
342                                 metaParameter.ParameterName = value;
343                         }
344                 }
345
346                 [DefaultValue (0)]
347                 public byte Precision {
348                         get { return metaParameter.Precision; }
349                         set { metaParameter.Precision = value; }
350                 }
351
352                 [DefaultValue (0)]
353                 public byte Scale {
354                         get { return metaParameter.Scale; }
355                         set { metaParameter.Scale = value; }
356                 }
357
358                 public override int Size {
359                         get { return metaParameter.Size; }
360                         set { metaParameter.Size = value; }
361                 }
362
363                 public override string SourceColumn {
364                         get {
365                                 if (sourceColumn == null)
366                                         return string.Empty;
367                                 return sourceColumn;
368                         }
369                         set { sourceColumn = value; }
370                 }
371
372                 public override DataRowVersion SourceVersion {
373                         get { return sourceVersion; }
374                         set { sourceVersion = value; }
375                 }
376                 
377                 [RefreshProperties (RefreshProperties.All)]
378                 [DbProviderSpecificTypeProperty(true)]
379                 public SqlDbType SqlDbType {
380                         get { return sqlDbType; }
381                         set {
382                                 SetSqlDbType (value);
383                                 typeChanged = true;
384                                 isTypeSet = true;
385                         }
386                 }
387
388                 [TypeConverterAttribute (typeof (StringConverter))]
389                 [RefreshProperties (RefreshProperties.All)]
390                 public override object Value {
391                         get {
392                                 if (sqlType != null)
393                                         return GetSqlValue (metaParameter.RawValue);
394                                 return metaParameter.RawValue;
395                         }
396                         set {
397                                 if (!isTypeSet) {
398                                         InferSqlType (value);
399                                 }
400
401                                 if (value is INullable) {
402                                         sqlType = value.GetType ();
403                                         value = SqlTypeToFrameworkType (value);
404                                 }
405                                 metaParameter.RawValue = value;
406                         }
407                 }
408
409                 [Browsable (false)]
410                 public SqlCompareOptions CompareInfo{
411                         get{ return compareInfo; }
412                         set{ compareInfo = value; }
413                 }
414
415                 [Browsable (false)]
416                 public int LocaleId { 
417                         get { return localeId; }
418                         set { localeId = value; }
419                 }
420
421                 [Browsable (false)]
422                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
423                 public Object SqlValue {
424                         get {
425                                 return GetSqlValue (metaParameter.RawValue);
426                         }
427                         set {
428                                 Value = value;
429                         }
430                 }
431         
432                 public override bool SourceColumnNullMapping {
433                         get { return sourceColumnNullMapping; }
434                         set { sourceColumnNullMapping = value; }
435                 }
436
437                 public string XmlSchemaCollectionDatabase {
438                         get { return xmlSchemaCollectionDatabase; }
439                         set { xmlSchemaCollectionDatabase = (value == null ? String.Empty : value); }
440                 }
441
442                 public string XmlSchemaCollectionName {
443                         get { return xmlSchemaCollectionName; }
444                         set {
445                                 xmlSchemaCollectionName = (value == null ? String.Empty : value);
446                         }
447                 }
448
449                 public string XmlSchemaCollectionOwningSchema {
450                         get { return xmlSchemaCollectionOwningSchema; } 
451                         set {
452                                 xmlSchemaCollectionOwningSchema = (value == null ? String.Empty : value);
453                         }
454                 }
455
456                 [BrowsableAttribute(false)]
457                 public string UdtTypeName { get; set; }
458
459                 #endregion // Properties
460
461                 #region Methods
462
463                 object ICloneable.Clone ()
464                 {
465                         return new SqlParameter (ParameterName, SqlDbType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
466                 }
467
468                 // If the value is set without the DbType/SqlDbType being set, then we
469                 // infer type information.
470                 void InferSqlType (object value)
471                 {
472                         if (value == null || value == DBNull.Value) {
473                                 SetSqlDbType (SqlDbType.NVarChar);
474                                 return;
475                         }
476
477                         Type type = value.GetType ();
478                         if (type.IsEnum)
479                                 type = Enum.GetUnderlyingType (type);
480                         object t = type_mapping [type];
481                         if (t == null)
482                                 throw new ArgumentException (String.Format ("The parameter data type of {0} is invalid.", type.FullName));
483                         SetSqlDbType ((SqlDbType) t);
484                 }
485
486                 // Returns System.Type corresponding to the underlying SqlDbType
487                 internal override Type SystemType {
488                         get {
489                                 return (Type) DbTypeMapping [sqlDbType];
490                         }
491                 }
492
493                 internal override object FrameworkDbType {
494                         get {
495                                 return sqlDbType;
496                         }
497                         
498                         set {
499                                 object t;
500                                 try {
501                                         t = (DbType) DbTypeFromName ((string)value);
502                                         SetDbType ((DbType)t);
503                                 } catch (ArgumentException) {
504                                         t = (SqlDbType)FrameworkDbTypeFromName ((string)value);
505                                         SetSqlDbType ((SqlDbType) t);
506                                 }
507                         }
508                 }
509
510                 DbType DbTypeFromName (string name)
511                 {
512                         switch (name.ToLower ()) {
513                                 case "ansistring":
514                                         return DbType.AnsiString;
515                                 case "ansistringfixedlength":
516                                         return DbType.AnsiStringFixedLength;
517                                 case "binary": 
518                                         return DbType.Binary;
519                                 case "boolean":
520                                         return DbType.Boolean;
521                                 case "byte":
522                                         return DbType.Byte;
523                                 case "currency": 
524                                         return DbType.Currency;
525                                 case "date":
526                                         return DbType.Date;
527                                 case "datetime": 
528                                         return DbType.DateTime;
529                                 case "decimal":
530                                         return DbType.Decimal;
531                                 case "double": 
532                                         return DbType.Double;
533                                 case "guid": 
534                                         return DbType.Guid;
535                                 case "int16": 
536                                         return DbType.Int16;
537                                 case "int32": 
538                                         return DbType.Int32;
539                                 case "int64": 
540                                         return DbType.Int64;
541                                 case "object": 
542                                         return DbType.Object;
543                                 case "single": 
544                                         return DbType.Single;
545                                 case "string": 
546                                         return DbType.String;
547                                 case "stringfixedlength": 
548                                         return DbType.StringFixedLength;
549                                 case "time": 
550                                         return DbType.Time;
551                                 case "xml": 
552                                         return DbType.Xml;
553                                 default:
554                                         string exception = String.Format ("No mapping exists from {0} to a known DbType.", name);
555                                         throw new ArgumentException (exception);
556                         }
557                 }
558
559                 // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
560                 // string representation of the type name.  If the DbType is not convertible
561                 // to an SqlDbType, throw an exception.
562                 private void SetDbType (DbType type)
563                 {
564                         switch (type) {
565                         case DbType.AnsiString:
566                                 MetaParameter.TypeName = "varchar";
567                                 sqlDbType = SqlDbType.VarChar;
568                                 MetaParameter.IsVariableSizeType = true;
569                                 break;
570                         case DbType.AnsiStringFixedLength:
571                                 MetaParameter.TypeName = "char";
572                                 sqlDbType = SqlDbType.Char;
573                                 MetaParameter.IsVariableSizeType = true;
574                                 break;
575                         case DbType.Binary:
576                                 MetaParameter.TypeName = "varbinary";
577                                 sqlDbType = SqlDbType.VarBinary;
578                                 MetaParameter.IsVariableSizeType = true;
579                                 break;
580                         case DbType.Boolean:
581                                 MetaParameter.TypeName = "bit";
582                                 sqlDbType = SqlDbType.Bit;
583                                 break;
584                         case DbType.Byte:
585                                 MetaParameter.TypeName = "tinyint";
586                                 sqlDbType = SqlDbType.TinyInt;
587                                 break;
588                         case DbType.Currency:
589                                 sqlDbType = SqlDbType.Money;
590                                 MetaParameter.TypeName = "money";
591                                 break;
592                         case DbType.Date:
593                         case DbType.DateTime:
594                                 MetaParameter.TypeName = "datetime";
595                                 sqlDbType = SqlDbType.DateTime;
596                                 break;
597                         case DbType.DateTime2:
598                                 MetaParameter.TypeName = "datetime2";
599                                 sqlDbType = SqlDbType.DateTime2;
600                                 break;
601                         case DbType.Decimal:
602                                 MetaParameter.TypeName = "decimal";
603                                 sqlDbType = SqlDbType.Decimal;
604                                 break;
605                         case DbType.Double:
606                                 MetaParameter.TypeName = "float";
607                                 sqlDbType = SqlDbType.Float;
608                                 break;
609                         case DbType.Guid:
610                                 MetaParameter.TypeName = "uniqueidentifier";
611                                 sqlDbType = SqlDbType.UniqueIdentifier;
612                                 break;
613                         case DbType.Int16:
614                                 MetaParameter.TypeName = "smallint";
615                                 sqlDbType = SqlDbType.SmallInt;
616                                 break;
617                         case DbType.Int32:
618                                 MetaParameter.TypeName = "int";
619                                 sqlDbType = SqlDbType.Int;
620                                 break;
621                         case DbType.Int64:
622                                 MetaParameter.TypeName = "bigint";
623                                 sqlDbType = SqlDbType.BigInt;
624                                 break;
625                         case DbType.Object:
626                                 MetaParameter.TypeName = "sql_variant";
627                                 sqlDbType = SqlDbType.Variant;
628                                 break;
629                         case DbType.Single:
630                                 MetaParameter.TypeName = "real";
631                                 sqlDbType = SqlDbType.Real;
632                                 break;
633                         case DbType.String:
634                                 MetaParameter.TypeName = "nvarchar";
635                                 sqlDbType = SqlDbType.NVarChar;
636                                 MetaParameter.IsVariableSizeType = true;
637                                 break;
638                         case DbType.StringFixedLength:
639                                 MetaParameter.TypeName = "nchar";
640                                 sqlDbType = SqlDbType.NChar;
641                                 MetaParameter.IsVariableSizeType = true;
642                                 break;
643                         case DbType.Time:
644                                 MetaParameter.TypeName = "datetime";
645                                 sqlDbType = SqlDbType.DateTime;
646                                 break;
647                                 // Handle Xml type as string
648                         case DbType.Xml:
649                                 MetaParameter.TypeName = "xml";
650                                 sqlDbType = SqlDbType.Xml;
651                                 MetaParameter.IsVariableSizeType = true;
652                                 break;
653                         default:
654                                 string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
655                                 throw new ArgumentException (exception);
656                         }
657                         dbType = type;
658                 }
659
660                 // Used by internal constructor which has a SQL Server typename
661                 private SqlDbType FrameworkDbTypeFromName (string dbTypeName)
662                 {
663                         switch (dbTypeName.ToLower ()) {        
664                         case "bigint":
665                                 return SqlDbType.BigInt;
666                         case "binary":
667                                 return SqlDbType.Binary;
668                         case "bit":
669                                 return SqlDbType.Bit;
670                         case "char":
671                                 return SqlDbType.Char;
672                         case "datetime":
673                                 return SqlDbType.DateTime;
674                         case "decimal":
675                                 return SqlDbType.Decimal;
676                         case "float":
677                                 return SqlDbType.Float;
678                         case "image":
679                                 return SqlDbType.Image;
680                         case "int":
681                                 return SqlDbType.Int;
682                         case "money":
683                                 return SqlDbType.Money;
684                         case "nchar":
685                                 return SqlDbType.NChar;
686                         case "ntext":
687                                 return SqlDbType.NText;
688                         case "nvarchar":
689                                 return SqlDbType.NVarChar;
690                         case "real":
691                                 return SqlDbType.Real;
692                         case "smalldatetime":
693                                 return SqlDbType.SmallDateTime;
694                         case "smallint":
695                                 return SqlDbType.SmallInt;
696                         case "smallmoney":
697                                 return SqlDbType.SmallMoney;
698                         case "text":
699                                 return SqlDbType.Text;
700                         case "timestamp":
701                                 return SqlDbType.Timestamp;
702                         case "tinyint":
703                                 return SqlDbType.TinyInt;
704                         case "uniqueidentifier":
705                                 return SqlDbType.UniqueIdentifier;
706                         case "varbinary":
707                                 return SqlDbType.VarBinary;
708                         case "varchar":
709                                 return SqlDbType.VarChar;
710                         case "sql_variant":
711                                 return SqlDbType.Variant;
712                         case "xml":
713                                 return SqlDbType.Xml;
714                         default:
715                                 return SqlDbType.Variant;
716                         }
717                 }
718
719                 // When the SqlDbType is set, we also set the DbType, as well as the SQL Server
720                 // string representation of the type name.  If the SqlDbType is not convertible
721                 // to a DbType, throw an exception.
722                 internal void SetSqlDbType (SqlDbType type)
723                 {
724                         switch (type) {
725                         case SqlDbType.BigInt:
726                                 MetaParameter.TypeName = "bigint";
727                                 dbType = DbType.Int64;
728                                 break;
729                         case SqlDbType.Binary:
730                                 MetaParameter.TypeName = "binary";
731                                 dbType = DbType.Binary;
732                                 MetaParameter.IsVariableSizeType = true;
733                                 break;
734                         case SqlDbType.Timestamp:
735                                 MetaParameter.TypeName = "timestamp";
736                                 dbType = DbType.Binary;
737                                 break;
738                         case SqlDbType.VarBinary:
739                                 MetaParameter.TypeName = "varbinary";
740                                 dbType = DbType.Binary;
741                                 MetaParameter.IsVariableSizeType = true;
742                                 break;
743                         case SqlDbType.Bit:
744                                 MetaParameter.TypeName = "bit";
745                                 dbType = DbType.Boolean;
746                                 break;
747                         case SqlDbType.Char:
748                                 MetaParameter.TypeName = "char";
749                                 dbType = DbType.AnsiStringFixedLength;
750                                 MetaParameter.IsVariableSizeType = true;
751                                 break;
752                         case SqlDbType.DateTime:
753                                 MetaParameter.TypeName = "datetime";
754                                 dbType = DbType.DateTime;
755                                 break;
756                         case SqlDbType.SmallDateTime:
757                                 MetaParameter.TypeName = "smalldatetime";
758                                 dbType = DbType.DateTime;
759                                 break;
760                         case SqlDbType.Decimal:
761                                 MetaParameter.TypeName = "decimal";
762                                 dbType = DbType.Decimal;
763                                 break;
764                         case SqlDbType.Float:
765                                 MetaParameter.TypeName = "float";
766                                 dbType = DbType.Double;
767                                 break;
768                         case SqlDbType.Image:
769                                 MetaParameter.TypeName = "image";
770                                 dbType = DbType.Binary;
771                                 MetaParameter.IsVariableSizeType = true;
772                                 break;
773                         case SqlDbType.Int:
774                                 MetaParameter.TypeName = "int";
775                                 dbType = DbType.Int32;
776                                 break;
777                         case SqlDbType.Money:
778                                 MetaParameter.TypeName = "money";
779                                 dbType = DbType.Currency;
780                                 break;
781                         case SqlDbType.SmallMoney:
782                                 MetaParameter.TypeName = "smallmoney";
783                                 dbType = DbType.Currency;
784                                 break;
785                         case SqlDbType.NChar:
786                                 MetaParameter.TypeName = "nchar";
787                                 dbType = DbType.StringFixedLength;
788                                 MetaParameter.IsVariableSizeType = true;
789                                 break;
790                         case SqlDbType.NText:
791                                 MetaParameter.TypeName = "ntext";
792                                 dbType = DbType.String;
793                                 MetaParameter.IsVariableSizeType = true;
794                                 break;
795                         case SqlDbType.NVarChar:
796                                 MetaParameter.TypeName = "nvarchar";
797                                 dbType = DbType.String;
798                                 MetaParameter.IsVariableSizeType = true;
799                                 break;
800                         case SqlDbType.Real:
801                                 MetaParameter.TypeName = "real";
802                                 dbType = DbType.Single;
803                                 break;
804                         case SqlDbType.SmallInt:
805                                 MetaParameter.TypeName = "smallint";
806                                 dbType = DbType.Int16;
807                                 break;
808                         case SqlDbType.Text:
809                                 MetaParameter.TypeName = "text";
810                                 dbType = DbType.AnsiString;
811                                 MetaParameter.IsVariableSizeType = true;
812                                 break;
813                         case SqlDbType.VarChar:
814                                 MetaParameter.TypeName = "varchar";
815                                 dbType = DbType.AnsiString;
816                                 MetaParameter.IsVariableSizeType = true;
817                                 break;
818                         case SqlDbType.TinyInt:
819                                 MetaParameter.TypeName = "tinyint";
820                                 dbType = DbType.Byte;
821                                 break;
822                         case SqlDbType.UniqueIdentifier:
823                                 MetaParameter.TypeName = "uniqueidentifier";
824                                 dbType = DbType.Guid;
825                                 break;
826                         case SqlDbType.Variant:
827                                 MetaParameter.TypeName = "sql_variant";
828                                 dbType = DbType.Object;
829                                 break;
830                         case SqlDbType.Xml:
831                                 MetaParameter.TypeName = "xml";
832                                 dbType = DbType.Xml;
833                                 MetaParameter.IsVariableSizeType = true;
834                                 break;
835                         default:
836                                 string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
837                                 throw new ArgumentOutOfRangeException ("SqlDbType", exception);
838                         }
839                         sqlDbType = type;
840                 }
841
842                 public override string ToString() 
843                 {
844                         return ParameterName;
845                 }
846
847                 object GetFrameworkValue (object rawValue, ref bool updated)
848                 {
849                         object tdsValue;
850
851                         updated = typeChanged || updated;
852                         if (updated) {
853                                 tdsValue = SqlTypeToFrameworkType (rawValue);
854                                 typeChanged = false;
855                         } else
856                                 tdsValue = null;
857                         return tdsValue;
858                 }
859                 
860                 // TODO: Code copied from SqlDataReader, need a better approach
861                 object GetSqlValue (object value)
862                 {               
863                         if (value == null)
864                                 return value;
865                         switch (sqlDbType) {
866                         case SqlDbType.BigInt:
867                                 if (value == DBNull.Value)
868                                         return SqlInt64.Null;
869                                 return (SqlInt64) ((long) value);
870                         case SqlDbType.Binary:
871                         case SqlDbType.Image:
872                         case SqlDbType.VarBinary:
873                         case SqlDbType.Timestamp:
874                                 if (value == DBNull.Value)
875                                         return SqlBinary.Null;
876                                 return (SqlBinary) (byte[]) value;
877                         case SqlDbType.Bit:
878                                 if (value == DBNull.Value)
879                                         return SqlBoolean.Null;
880                                 return (SqlBoolean) ((bool) value);
881                         case SqlDbType.Char:
882                         case SqlDbType.NChar:
883                         case SqlDbType.NText:
884                         case SqlDbType.NVarChar:
885                         case SqlDbType.Text:
886                         case SqlDbType.VarChar:
887                                 if (value == DBNull.Value)
888                                         return SqlString.Null;
889
890                                 string str;
891                                 Type type = value.GetType ();
892                                 if (type == typeof (char))
893                                         str = value.ToString ();
894                                 else if (type == typeof (char[]))
895                                         str = new String ((char[])value);
896                                 else
897                                         str = ((string)value);
898                                         return (SqlString) str;
899                         case SqlDbType.DateTime:
900                         case SqlDbType.SmallDateTime:
901                                 if (value == DBNull.Value)
902                                         return SqlDateTime.Null;
903                                 return (SqlDateTime) ((DateTime) value);
904                         case SqlDbType.Decimal:
905                                 if (value == DBNull.Value)
906                                         return SqlDecimal.Null;
907                                 if (value is TdsBigDecimal)
908                                         return SqlDecimalExtensions.FromTdsBigDecimal ((TdsBigDecimal) value);
909                                 return (SqlDecimal) ((decimal) value);
910                         case SqlDbType.Float:
911                                 if (value == DBNull.Value)
912                                         return SqlDouble.Null;
913                                 return (SqlDouble) ((double) value);
914                         case SqlDbType.Int:
915                                 if (value == DBNull.Value)
916                                         return SqlInt32.Null;
917                                 return (SqlInt32) ((int) value);
918                         case SqlDbType.Money:
919                         case SqlDbType.SmallMoney:
920                                 if (value == DBNull.Value)
921                                         return SqlMoney.Null;
922                                 return (SqlMoney) ((decimal) value);
923                         case SqlDbType.Real:
924                                 if (value == DBNull.Value)
925                                         return SqlSingle.Null;
926                                 return (SqlSingle) ((float) value);
927                         case SqlDbType.UniqueIdentifier:
928                                 if (value == DBNull.Value)
929                                         return SqlGuid.Null;
930                                 return (SqlGuid) ((Guid) value);
931                         case SqlDbType.SmallInt:
932                                 if (value == DBNull.Value)
933                                         return SqlInt16.Null;
934                                 return (SqlInt16) ((short) value);
935                         case SqlDbType.TinyInt:
936                                 if (value == DBNull.Value)
937                                         return SqlByte.Null;
938                                 return (SqlByte) ((byte) value);
939                         case SqlDbType.Xml:
940                                 if (value == DBNull.Value)
941                                         return SqlXml.Null;
942                                 return (SqlXml) value;
943                         default:
944                                 throw new NotImplementedException ("Type '" + sqlDbType + "' not implemented.");
945                         }
946                 }
947                 
948                 object SqlTypeToFrameworkType (object value)
949                 {
950                         INullable nullable = value as INullable;
951                         if (nullable == null)
952                                 return ConvertToFrameworkType (value);
953
954                         if (nullable.IsNull)
955                                 return DBNull.Value;
956
957                         Type type = value.GetType ();
958                         // Map to .net type, as Mono TDS respects only types from .net
959
960                         if (typeof (SqlString) == type) {
961                                 return ((SqlString) value).Value;
962                         }
963
964                         if (typeof (SqlInt16) == type) {
965                                 return ((SqlInt16) value).Value;
966                         }
967
968                         if (typeof (SqlInt32) == type) {
969                                 return ((SqlInt32) value).Value;
970                         }
971
972                         if (typeof (SqlDateTime) == type) {
973                                 return ((SqlDateTime) value).Value;
974                         }
975
976                         if (typeof (SqlInt64) == type) {
977                                 return ((SqlInt64) value).Value;
978                         }
979
980                         if (typeof (SqlBinary) == type) {
981                                 return ((SqlBinary) value).Value;
982                         }
983                         
984                         if (typeof (SqlBytes) == type) {
985                                 return ((SqlBytes) value).Value;
986                         }
987
988                         if (typeof (SqlChars) == type) {
989                                 return ((SqlChars) value).Value;
990                         }
991
992                         if (typeof (SqlBoolean) == type) {
993                                 return ((SqlBoolean) value).Value;
994                         }
995
996                         if (typeof (SqlByte) == type) {
997                                 return ((SqlByte) value).Value;
998                         }
999
1000                         if (typeof (SqlDecimal) == type) {
1001                                 return ((SqlDecimal) value).Value;
1002                         }
1003
1004                         if (typeof (SqlDouble) == type) {
1005                                 return ((SqlDouble) value).Value;
1006                         }
1007
1008                         if (typeof (SqlGuid) == type) {
1009                                 return ((SqlGuid) value).Value;
1010                         }
1011
1012                         if (typeof (SqlMoney) == type) {
1013                                 return ((SqlMoney) value).Value;
1014                         }
1015
1016                         if (typeof (SqlSingle) == type) {
1017                                 return ((SqlSingle) value).Value;
1018                         }
1019
1020                         return value;
1021                 }
1022
1023                 internal object ConvertToFrameworkType (object value)
1024                 {
1025                         if (value == null || value == DBNull.Value)
1026                                 return value;
1027                         if (sqlDbType == SqlDbType.Variant)
1028                                 return metaParameter.Value;
1029
1030                         Type frameworkType = SystemType;
1031                         if (frameworkType == null)
1032                                 throw new NotImplementedException ("Type Not Supported : " + sqlDbType.ToString());
1033
1034                         Type valueType = value.GetType ();
1035                         if (valueType == frameworkType)
1036                                 return value;
1037
1038                         object sqlvalue = null;
1039
1040                         try {
1041                                 sqlvalue = ConvertToFrameworkType (value, frameworkType);
1042                         } catch (FormatException ex) {
1043                                 throw new FormatException (string.Format (CultureInfo.InvariantCulture,
1044                                         "Parameter value could not be converted from {0} to {1}.",
1045                                         valueType.Name, frameworkType.Name), ex);
1046                         }
1047
1048                         return sqlvalue;
1049                 }
1050
1051                 object ConvertToFrameworkType (object value, Type frameworkType)
1052                 {
1053                         object sqlvalue = Convert.ChangeType (value, frameworkType);
1054                         switch (sqlDbType) {
1055                         case SqlDbType.Money:
1056                         case SqlDbType.SmallMoney:
1057                                 sqlvalue = Decimal.Round ((decimal) sqlvalue, 4);
1058                                 break;
1059                         }
1060                         return sqlvalue;
1061                 }
1062
1063                 public override void ResetDbType ()
1064                 {
1065                         InferSqlType (Value);
1066                 }
1067
1068                 public void ResetSqlDbType ()
1069                 {
1070                         InferSqlType (Value);
1071                 }
1072
1073                 #endregion // Methods
1074         }
1075 }