Merge pull request #1949 from lewurm/fixtype
[mono.git] / mcs / class / System.Data / System.Data.SqlClient / SqlParameter.cs
index 38e6e36f8c52c69e54c9d9e4810e0e20bd6aa840..f011f7cb3b9d4feb9c015c1131ef9e6cb9a20e62 100644 (file)
@@ -8,13 +8,14 @@
 //   Diego Caravana (diego@toth.it)
 //   Umadevi S (sumadevi@novell.com)
 //   Amit Biswas (amit@amitbiswas.com)
+//   Veerapuram Varadhan (vvaradhan@novell.com)
 //
 // (C) Ximian, Inc. 2002
 // Copyright (C) Tim Coleman, 2002
 //
 
 //
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004, 2008, 2009 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -44,19 +45,30 @@ using System.ComponentModel;
 using System.Data;
 using System.Data.Common;
 using System.Data.SqlTypes;
+using System.Globalization;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Xml;
 
 namespace System.Data.SqlClient {
-#if NET_2_0
        [TypeConverterAttribute ("System.Data.SqlClient.SqlParameter+SqlParameterConverter, " + Consts.AssemblySystem_Data)]
        public sealed class SqlParameter : DbParameter, IDbDataParameter, IDataParameter, ICloneable
-#else
-       [TypeConverterAttribute (typeof (SqlParameterConverter))]
-       public sealed class SqlParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
-#endif // NET_2_0
        {
+#region Import from old DbParameter
+               static Hashtable dbTypeMapping = new Hashtable ();
+                internal static Hashtable DbTypeMapping {
+                        get { return dbTypeMapping;}
+                        set { dbTypeMapping = value;}
+                }
+
+                // LAMESPEC: Implementors should populate the dbTypeMapping accordingly
+                internal Type SystemType {
+                        get {
+                                return (Type) dbTypeMapping [SqlDbType];
+                        }
+                }
+#endregion
+
                #region Fields
 
                TdsMetaParameter metaParameter;
@@ -73,12 +85,10 @@ namespace System.Data.SqlClient {
                int localeId;
                Type sqlType;
                bool typeChanged;
-#if NET_2_0
                bool sourceColumnNullMapping;
                string xmlSchemaCollectionDatabase = String.Empty;
                string xmlSchemaCollectionOwningSchema = String.Empty;
                string xmlSchemaCollectionName = String.Empty;
-#endif
 
                static Hashtable type_mapping;
 
@@ -89,17 +99,27 @@ namespace System.Data.SqlClient {
                
                static SqlParameter ()
                {
-
-#if NET_2_0
                        if (DbTypeMapping == null)
                                DbTypeMapping = new Hashtable ();
                        
                        DbTypeMapping.Add (SqlDbType.BigInt, typeof (long));
                        DbTypeMapping.Add (SqlDbType.Bit, typeof (bool));
+                       DbTypeMapping.Add (SqlDbType.Char, typeof (string));
+                       DbTypeMapping.Add (SqlDbType.NChar, typeof (string));
+                       DbTypeMapping.Add (SqlDbType.Text, typeof (string));
+                       DbTypeMapping.Add (SqlDbType.NText, typeof (string));
+                       DbTypeMapping.Add (SqlDbType.VarChar, typeof (string));
                        DbTypeMapping.Add (SqlDbType.NVarChar, typeof (string));
+                       DbTypeMapping.Add (SqlDbType.SmallDateTime, typeof (DateTime));
                        DbTypeMapping.Add (SqlDbType.DateTime, typeof (DateTime));
+                       DbTypeMapping.Add (SqlDbType.DateTime2, typeof (DateTime));
+                       DbTypeMapping.Add (SqlDbType.DateTimeOffset, typeof (DateTimeOffset));
                        DbTypeMapping.Add (SqlDbType.Decimal, typeof (decimal));
                        DbTypeMapping.Add (SqlDbType.Float, typeof (double));
+                       DbTypeMapping.Add (SqlDbType.Binary, typeof (byte []));
+                       DbTypeMapping.Add (SqlDbType.Image, typeof (byte []));
+                       DbTypeMapping.Add (SqlDbType.Money, typeof (decimal));
+                       DbTypeMapping.Add (SqlDbType.SmallMoney, typeof (decimal));
                        DbTypeMapping.Add (SqlDbType.VarBinary, typeof (byte []));
                        DbTypeMapping.Add (SqlDbType.TinyInt, typeof (byte));
                        DbTypeMapping.Add (SqlDbType.Int, typeof (int));
@@ -107,7 +127,8 @@ namespace System.Data.SqlClient {
                        DbTypeMapping.Add (SqlDbType.SmallInt, typeof (short));
                        DbTypeMapping.Add (SqlDbType.UniqueIdentifier, typeof (Guid));
                        DbTypeMapping.Add (SqlDbType.Variant, typeof (object));
-#endif
+                       DbTypeMapping.Add (SqlDbType.Xml, typeof (string));
+
                        type_mapping = new Hashtable ();
 
                        type_mapping.Add (typeof (long), SqlDbType.BigInt);
@@ -116,11 +137,10 @@ namespace System.Data.SqlClient {
                        type_mapping.Add (typeof (bool), SqlDbType.Bit);
                        type_mapping.Add (typeof (SqlTypes.SqlBoolean), SqlDbType.Bit);
 
-#if NET_2_0
                        type_mapping.Add (typeof (char), SqlDbType.NVarChar);
                        type_mapping.Add (typeof (char []), SqlDbType.NVarChar);
                        type_mapping.Add (typeof (SqlTypes.SqlChars), SqlDbType.NVarChar);
-#endif
+
                        type_mapping.Add (typeof (string), SqlDbType.NVarChar);
                        type_mapping.Add (typeof (SqlTypes.SqlString), SqlDbType.NVarChar);
 
@@ -135,9 +155,8 @@ namespace System.Data.SqlClient {
 
                        type_mapping.Add (typeof (byte []), SqlDbType.VarBinary);
                        type_mapping.Add (typeof (SqlTypes.SqlBinary), SqlDbType.VarBinary);
-#if NET_2_0
+
                        type_mapping.Add (typeof (SqlTypes.SqlBytes), SqlDbType.VarBinary);
-#endif
 
                        type_mapping.Add (typeof (byte), SqlDbType.TinyInt);
                        type_mapping.Add (typeof (SqlTypes.SqlByte), SqlDbType.TinyInt);
@@ -156,12 +175,11 @@ namespace System.Data.SqlClient {
 
                        type_mapping.Add (typeof (SqlTypes.SqlMoney), SqlDbType.Money);
 
-#if NET_2_0
                        type_mapping.Add (typeof (XmlReader), SqlDbType.Xml);
                        type_mapping.Add (typeof (SqlTypes.SqlXml), SqlDbType.Xml);
-#endif
 
                        type_mapping.Add (typeof (object), SqlDbType.Variant);
+                       type_mapping.Add (typeof (DateTimeOffset), SqlDbType.DateTimeOffset);
                }
                
                public SqlParameter () 
@@ -205,15 +223,13 @@ namespace System.Data.SqlClient {
                                                              isNullable, precision, 
                                                              scale,
                                                              GetFrameworkValue);
-                       metaParameter.RawValue = value;
-                       if (dbType != SqlDbType.Variant) 
-                               SqlDbType = dbType;
+                       metaParameter.RawValue =  value;
+                       SqlDbType = dbType;
                        Direction = direction;
                        SourceColumn = sourceColumn;
                        SourceVersion = sourceVersion;
                }
 
-#if NET_2_0
                public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, Object value, string xmlSchemaCollectionDatabase, string xmlSchemaCollectionOwningSchema, string xmlSchemaCollectionName)
                        : this (parameterName, dbType, size, direction, false, precision, scale, sourceColumn, sourceVersion, value)
                {
@@ -222,7 +238,6 @@ namespace System.Data.SqlClient {
                        XmlSchemaCollectionName = xmlSchemaCollectionName;
                        SourceColumnNullMapping = sourceColumnNullMapping;
                }
-#endif
 
                // This constructor is used internally to construct a
                // SqlParameter.  The value array comes from sp_procedure_params_rowset.
@@ -291,18 +306,7 @@ namespace System.Data.SqlClient {
                        }
                }
        
-#if ONLY_1_0 || ONLY_1_1
-               [Browsable (false)]
-               [DataSysDescription ("The parameter generic type.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               [RefreshProperties (RefreshProperties.All)]
-               [DataCategory ("Data")]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               DbType DbType {
+               public override DbType DbType {
                        get { return dbType; }
                        set {
                                SetDbType (value);
@@ -311,18 +315,8 @@ namespace System.Data.SqlClient {
                        }
                }
 
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("Input, output, or bidirectional parameter.")]
-               [DefaultValue (ParameterDirection.Input)]
-#endif
-#if NET_2_0
                [RefreshProperties (RefreshProperties.All)]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
+               public override
                ParameterDirection Direction {
                        get { return direction; }
                        set { 
@@ -345,45 +339,19 @@ namespace System.Data.SqlClient {
                        get { return metaParameter; }
                }
 
-#if ONLY_1_0 || ONLY_1_1
-               [Browsable (false)]
-               [DataSysDescription ("a design-time property used for strongly typed code-generation.")]
-               [DefaultValue (false)]
-               [DesignOnly (true)]
-               [EditorBrowsable (EditorBrowsableState.Advanced)]        
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               bool IsNullable {
+               public override bool IsNullable {
                        get { return metaParameter.IsNullable; }
                        set { metaParameter.IsNullable = value; }
                }
 
                [Browsable (false)]
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("Offset in variable length data types.")]
-               [DefaultValue (0)]
-#endif
-#if NET_2_0
                [EditorBrowsable (EditorBrowsableState.Advanced)]
-#endif
                public int Offset {
                        get { return offset; }
                        set { offset = value; }
                }
        
-#if ONLY_1_0 || ONLY_1_1
-               [DataSysDescription ("Name of the parameter, like '@p1'")]
-               [DefaultValue ("")]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               string ParameterName {
+               public override string ParameterName {
                        get { return metaParameter.ParameterName; }
                        set {
                                if (value == null)
@@ -393,49 +361,23 @@ namespace System.Data.SqlClient {
                }
 
                [DefaultValue (0)]
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
-#endif
                public byte Precision {
                        get { return metaParameter.Precision; }
                        set { metaParameter.Precision = value; }
                }
 
                [DefaultValue (0)]
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
-#endif
                public byte Scale {
                        get { return metaParameter.Scale; }
                        set { metaParameter.Scale = value; }
                }
 
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("Size of variable length data types (string & arrays).")]
-               [DefaultValue (0)]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               int Size {
+               public override int Size {
                        get { return metaParameter.Size; }
                        set { metaParameter.Size = value; }
                }
 
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("When used by a DataAdapter.Update, the source column name that is used to find the DataSetColumn name in the ColumnMappings. This is to copy a value between the parameter and a datarow.")]
-               [DefaultValue ("")]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               string SourceColumn {
+               public override string SourceColumn {
                        get {
                                if (sourceColumn == null)
                                        return string.Empty;
@@ -444,29 +386,13 @@ namespace System.Data.SqlClient {
                        set { sourceColumn = value; }
                }
 
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("When used by a DataAdapter.Update (UpdateCommand only), the version of the DataRow value that is used to update the data source.")]
-               [DefaultValue (DataRowVersion.Current)]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               DataRowVersion SourceVersion {
+               public override DataRowVersion SourceVersion {
                        get { return sourceVersion; }
                        set { sourceVersion = value; }
                }
                
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("The parameter native type.")]
-               [DefaultValue (SqlDbType.NVarChar)]
-#endif
                [RefreshProperties (RefreshProperties.All)]
-#if NET_2_0
                [DbProviderSpecificTypeProperty(true)]
-#endif
                public SqlDbType SqlDbType {
                        get { return sqlDbType; }
                        set {
@@ -477,31 +403,16 @@ namespace System.Data.SqlClient {
                }
 
                [TypeConverterAttribute (typeof (StringConverter))]
-#if ONLY_1_0 || ONLY_1_1
-               [DataCategory ("Data")]
-               [DataSysDescription ("Value of the parameter.")]
-               [DefaultValue (null)]
-#else
                [RefreshProperties (RefreshProperties.All)]
-#endif
-               public 
-#if NET_2_0
-               override
-#endif // NET_2_0
-               object Value {
+               public override object Value {
                        get {
                                if (sqlType != null)
-                                       return FrameworkTypeToSqlType (metaParameter.RawValue);
+                                       return GetSqlValue (metaParameter.RawValue);
                                return metaParameter.RawValue;
                        }
                        set {
                                if (!isTypeSet) {
-#if NET_2_0
                                        InferSqlType (value);
-#else
-                                       if (value != null && value != DBNull.Value)
-                                               InferSqlType (value);
-#endif
                                }
 
                                if (value is INullable) {
@@ -512,7 +423,6 @@ namespace System.Data.SqlClient {
                        }
                }
 
-#if NET_2_0
                [Browsable (false)]
                public SqlCompareOptions CompareInfo{
                        get{ return compareInfo; }
@@ -529,10 +439,7 @@ namespace System.Data.SqlClient {
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public Object SqlValue {
                        get {
-                               object value = metaParameter.RawValue;
-                               if (value != null)
-                                       return FrameworkTypeToSqlType (value);
-                               return null;
+                               return GetSqlValue (metaParameter.RawValue);
                        }
                        set {
                                Value = value;
@@ -562,7 +469,10 @@ namespace System.Data.SqlClient {
                                xmlSchemaCollectionOwningSchema = (value == null ? String.Empty : value);
                        }
                }
-#endif
+
+               [BrowsableAttribute(false)]
+               public string UdtTypeName { get; set; }
+
                #endregion // Properties
 
                #region Methods
@@ -590,14 +500,14 @@ namespace System.Data.SqlClient {
                        SetSqlDbType ((SqlDbType) t);
                }
 
-#if NET_2_0
+/*
                // Returns System.Type corresponding to the underlying SqlDbType
                internal override Type SystemType {
                        get {
                                return (Type) DbTypeMapping [sqlDbType];
                        }
                }
-               
+
                internal override object FrameworkDbType {
                        get {
                                return sqlDbType;
@@ -614,6 +524,7 @@ namespace System.Data.SqlClient {
                                }
                        }
                }
+*/
 
                DbType DbTypeFromName (string name)
                {
@@ -663,7 +574,6 @@ namespace System.Data.SqlClient {
                                        throw new ArgumentException (exception);
                        }
                }
-#endif
 
                // When the DbType is set, we also set the SqlDbType, as well as the SQL Server
                // string representation of the type name.  If the DbType is not convertible
@@ -703,6 +613,10 @@ namespace System.Data.SqlClient {
                                MetaParameter.TypeName = "datetime";
                                sqlDbType = SqlDbType.DateTime;
                                break;
+                       case DbType.DateTime2:
+                               MetaParameter.TypeName = "datetime2";
+                               sqlDbType = SqlDbType.DateTime2;
+                               break;
                        case DbType.Decimal:
                                MetaParameter.TypeName = "decimal";
                                sqlDbType = SqlDbType.Decimal;
@@ -749,14 +663,12 @@ namespace System.Data.SqlClient {
                                MetaParameter.TypeName = "datetime";
                                sqlDbType = SqlDbType.DateTime;
                                break;
-#if NET_2_0
                                // Handle Xml type as string
                        case DbType.Xml:
                                MetaParameter.TypeName = "xml";
                                sqlDbType = SqlDbType.Xml;
                                MetaParameter.IsVariableSizeType = true;
                                break;
-#endif
                        default:
                                string exception = String.Format ("No mapping exists from DbType {0} to a known SqlDbType.", type);
                                throw new ArgumentException (exception);
@@ -816,10 +728,8 @@ namespace System.Data.SqlClient {
                                return SqlDbType.VarChar;
                        case "sql_variant":
                                return SqlDbType.Variant;
-#if NET_2_0
                        case "xml":
                                return SqlDbType.Xml;
-#endif
                        default:
                                return SqlDbType.Variant;
                        }
@@ -866,6 +776,14 @@ namespace System.Data.SqlClient {
                                MetaParameter.TypeName = "smalldatetime";
                                dbType = DbType.DateTime;
                                break;
+                       case SqlDbType.DateTime2:
+                               MetaParameter.TypeName = "datetime2";
+                               dbType = DbType.DateTime2;
+                               break;
+                       case SqlDbType.DateTimeOffset:
+                               MetaParameter.TypeName = "datetimeoffset";
+                               dbType = DbType.DateTimeOffset;
+                               break;
                        case SqlDbType.Decimal:
                                MetaParameter.TypeName = "decimal";
                                dbType = DbType.Decimal;
@@ -936,13 +854,11 @@ namespace System.Data.SqlClient {
                                MetaParameter.TypeName = "sql_variant";
                                dbType = DbType.Object;
                                break;
-#if NET_2_0
                        case SqlDbType.Xml:
                                MetaParameter.TypeName = "xml";
                                dbType = DbType.Xml;
                                MetaParameter.IsVariableSizeType = true;
                                break;
-#endif
                        default:
                                string exception = String.Format ("No mapping exists from SqlDbType {0} to a known DbType.", type);
                                throw new ArgumentOutOfRangeException ("SqlDbType", exception);
@@ -967,7 +883,95 @@ namespace System.Data.SqlClient {
                                tdsValue = null;
                        return tdsValue;
                }
-
+               
+               // TODO: Code copied from SqlDataReader, need a better approach
+               object GetSqlValue (object value)
+               {               
+                       if (value == null)
+                               return value;
+                       switch (sqlDbType) {
+                       case SqlDbType.BigInt:
+                               if (value == DBNull.Value)
+                                       return SqlInt64.Null;
+                               return (SqlInt64) ((long) value);
+                       case SqlDbType.Binary:
+                       case SqlDbType.Image:
+                       case SqlDbType.VarBinary:
+                       case SqlDbType.Timestamp:
+                               if (value == DBNull.Value)
+                                       return SqlBinary.Null;
+                               return (SqlBinary) (byte[]) value;
+                       case SqlDbType.Bit:
+                               if (value == DBNull.Value)
+                                       return SqlBoolean.Null;
+                               return (SqlBoolean) ((bool) value);
+                       case SqlDbType.Char:
+                       case SqlDbType.NChar:
+                       case SqlDbType.NText:
+                       case SqlDbType.NVarChar:
+                       case SqlDbType.Text:
+                       case SqlDbType.VarChar:
+                               if (value == DBNull.Value)
+                                       return SqlString.Null;
+
+                               string str;
+                               Type type = value.GetType ();
+                               if (type == typeof (char))
+                                       str = value.ToString ();
+                               else if (type == typeof (char[]))
+                                       str = new String ((char[])value);
+                               else
+                                       str = ((string)value);
+                                       return (SqlString) str;
+                       case SqlDbType.DateTime:
+                       case SqlDbType.SmallDateTime:
+                               if (value == DBNull.Value)
+                                       return SqlDateTime.Null;
+                               return (SqlDateTime) ((DateTime) value);
+                       case SqlDbType.Decimal:
+                               if (value == DBNull.Value)
+                                       return SqlDecimal.Null;
+                               if (value is TdsBigDecimal)
+                                       return SqlDecimalExtensions.FromTdsBigDecimal ((TdsBigDecimal) value);
+                               return (SqlDecimal) ((decimal) value);
+                       case SqlDbType.Float:
+                               if (value == DBNull.Value)
+                                       return SqlDouble.Null;
+                               return (SqlDouble) ((double) value);
+                       case SqlDbType.Int:
+                               if (value == DBNull.Value)
+                                       return SqlInt32.Null;
+                               return (SqlInt32) ((int) value);
+                       case SqlDbType.Money:
+                       case SqlDbType.SmallMoney:
+                               if (value == DBNull.Value)
+                                       return SqlMoney.Null;
+                               return (SqlMoney) ((decimal) value);
+                       case SqlDbType.Real:
+                               if (value == DBNull.Value)
+                                       return SqlSingle.Null;
+                               return (SqlSingle) ((float) value);
+                       case SqlDbType.UniqueIdentifier:
+                               if (value == DBNull.Value)
+                                       return SqlGuid.Null;
+                               return (SqlGuid) ((Guid) value);
+                       case SqlDbType.SmallInt:
+                               if (value == DBNull.Value)
+                                       return SqlInt16.Null;
+                               return (SqlInt16) ((short) value);
+                       case SqlDbType.TinyInt:
+                               if (value == DBNull.Value)
+                                       return SqlByte.Null;
+                               return (SqlByte) ((byte) value);
+                       case SqlDbType.Xml:
+                               if (value == DBNull.Value)
+                                       return SqlXml.Null;
+                               return (SqlXml) value;
+                       default:
+                               throw new NotImplementedException ("Type '" + sqlDbType + "' not implemented.");
+                       }
+               }
+               
                object SqlTypeToFrameworkType (object value)
                {
                        INullable nullable = value as INullable;
@@ -1003,6 +1007,14 @@ namespace System.Data.SqlClient {
                        if (typeof (SqlBinary) == type) {
                                return ((SqlBinary) value).Value;
                        }
+                       
+                       if (typeof (SqlBytes) == type) {
+                               return ((SqlBytes) value).Value;
+                       }
+
+                       if (typeof (SqlChars) == type) {
+                               return ((SqlChars) value).Value;
+                       }
 
                        if (typeof (SqlBoolean) == type) {
                                return ((SqlBoolean) value).Value;
@@ -1035,217 +1047,53 @@ namespace System.Data.SqlClient {
                        return value;
                }
 
-               static object GetSqlNullValue (Type sqlType)
-               {
-                       if (sqlType == typeof (SqlBinary))
-                               return SqlBinary.Null;
-                       if (sqlType == typeof (SqlBoolean))
-                               return SqlBoolean.Null;
-                       if (sqlType == typeof (SqlByte))
-                               return SqlByte.Null;
-#if NET_2_0
-                       if (sqlType == typeof (SqlBytes))
-                               return SqlBytes.Null;
-                       if (sqlType == typeof (SqlChars))
-                               return SqlChars.Null;
-#endif
-                       if (sqlType == typeof (SqlDateTime))
-                               return SqlDateTime.Null;
-                       if (sqlType == typeof (SqlDecimal))
-                               return SqlDecimal.Null;
-                       if (sqlType == typeof (SqlDouble))
-                               return SqlDouble.Null;
-                       if (sqlType == typeof (SqlInt16))
-                               return SqlInt16.Null;
-                       if (sqlType == typeof (SqlInt32))
-                               return SqlInt32.Null;
-                       if (sqlType == typeof (SqlInt64))
-                               return SqlInt64.Null;
-                       if (sqlType == typeof (SqlMoney))
-                               return SqlMoney.Null;
-                       if (sqlType == typeof (SqlSingle))
-                               return SqlSingle.Null;
-                       if (sqlType == typeof (SqlString))
-                               return SqlString.Null;
-#if NET_2_0
-                       if (sqlType == typeof (SqlXml))
-                               return SqlXml.Null;
-#endif
-                       if (sqlType == typeof (SqlGuid))
-                               return SqlGuid.Null;
-
-                       throw new NotImplementedException ("Type '" + sqlType.FullName + "' not implemented.");
-               }
-
-               static object GetSqlNullValue (SqlDbType sqlDbType)
-               {
-                       switch (sqlDbType) {
-                       case SqlDbType.BigInt:
-                               return SqlInt64.Null;
-                       case SqlDbType.Binary:
-                       case SqlDbType.Image:
-                       case SqlDbType.VarBinary:
-                               return SqlBinary.Null;
-                       case SqlDbType.Bit:
-                               return SqlBoolean.Null;
-                       case SqlDbType.Int:
-                               return SqlInt32.Null;
-                       case SqlDbType.SmallInt:
-                               return SqlInt16.Null;
-                       case SqlDbType.TinyInt:
-                               return SqlByte.Null;
-                       case SqlDbType.Float:
-                       case SqlDbType.Real:
-                               return SqlSingle.Null;
-                       case SqlDbType.Decimal:
-                               return SqlDecimal.Null;
-                       case SqlDbType.Money:
-                       case SqlDbType.SmallMoney:
-                               return SqlMoney.Null;
-                       case SqlDbType.DateTime:
-                       case SqlDbType.SmallDateTime:
-                               return SqlDateTime.Null;
-                       case SqlDbType.VarChar:
-                       case SqlDbType.NVarChar:
-                       case SqlDbType.Char:
-                       case SqlDbType.NChar:
-                       case SqlDbType.Text:
-                       case SqlDbType.NText:
-                               return SqlString.Null;
-#if NET_2_0
-                       case SqlDbType.Xml:
-                               return SqlXml.Null;
-#endif
-                       case SqlDbType.UniqueIdentifier:
-                               return SqlGuid.Null;
-                       default:
-                               throw new NotImplementedException ("Type '" + sqlDbType + "' not implemented.");
-                       }
-               }
-
-               object FrameworkTypeToSqlType (object value)
+               internal object ConvertToFrameworkType (object value)
                {
-                       if (value == null || value == DBNull.Value) {
-                               if (sqlType != null)
-                                       return GetSqlNullValue (sqlType);
-                               else
-                                       return GetSqlNullValue (SqlDbType);
-                       }
-
-                       Type type = value.GetType ();
-
-                       if (type == typeof (string))
-                               return new SqlString ((string) value);
-
-                       if (type == typeof (short))
-                               return new SqlInt16 ((short) value);
-
-                       if (type == typeof (int))
-                               return new SqlInt32 ((int) value);
-
-                       if (type == typeof (DateTime))
-                               return new SqlDateTime ((DateTime) value);
-
-                       if (type == typeof (long))
-                               return new SqlInt64 ((long) value);
-
-#if NET_2_0
-                       if (type == typeof (char))
-                               return new SqlString (((char) value).ToString ());
-
-                       if (type == typeof (char []))
-                               return new SqlString (new string ((char []) value));
-#endif
-
-                       if (type == typeof (byte))
-                               return new SqlByte ((byte) value);
+                       if (value == null || value == DBNull.Value)
+                               return value;
+                       if (sqlDbType == SqlDbType.Variant)
+                               return metaParameter.Value;
 
-                       if (type == typeof (byte []))
-                               return new SqlBinary ((byte []) value);
+                       Type frameworkType = SystemType;
+                       if (frameworkType == null)
+                               throw new NotImplementedException ("Type Not Supported : " + sqlDbType.ToString());
 
-                       if (type == typeof (bool))
-                               return new SqlBoolean ((bool) value);
+                       Type valueType = value.GetType ();
+                       if (valueType == frameworkType)
+                               return value;
 
-                       if (type == typeof (byte))
-                               return new SqlByte ((byte) value);
+                       object sqlvalue = null;
 
-                       if (type == typeof (decimal)) {
-                               if (sqlType != null && sqlType == typeof (SqlMoney))
-                                       return new SqlMoney ((decimal) value);
-                               return new SqlDecimal ((decimal) value);
+                       try {
+                               sqlvalue = ConvertToFrameworkType (value, frameworkType);
+                       } catch (FormatException ex) {
+                               throw new FormatException (string.Format (CultureInfo.InvariantCulture,
+                                       "Parameter value could not be converted from {0} to {1}.",
+                                       valueType.Name, frameworkType.Name), ex);
                        }
 
-                       if (type == typeof (double))
-                               return new SqlDouble ((double) value);
-
-                       if (type == typeof (Guid))
-                               return new SqlGuid ((Guid) value);
-
-                       if (type == typeof (float))
-                               return new SqlSingle ((float) value);
-
-                       return value;
+                       return sqlvalue;
                }
 
-               internal object ConvertToFrameworkType (object value)
+               object ConvertToFrameworkType (object value, Type frameworkType)
                {
-                       if (value == null || value == DBNull.Value)
-                               return value;
-                       
-                       if (value is string && ((string)value).Length == 0)
-                               return DBNull.Value;
-                       
-                       switch (sqlDbType)  {
-                       case SqlDbType.BigInt :
-                               return Convert.ChangeType (value, typeof (Int64));
-                       case SqlDbType.Binary:
-                       case SqlDbType.Image:
-                       case SqlDbType.VarBinary:
-                               if (value is byte[])
-                                       return value;
-                               break;
-                       case SqlDbType.Bit:
-                               return Convert.ChangeType (value, typeof (bool));
-                       case SqlDbType.Int:
-                               return Convert.ChangeType (value, typeof (Int32));
-                       case SqlDbType.SmallInt :
-                               return Convert.ChangeType (value, typeof (Int16));
-                       case SqlDbType.TinyInt :
-                               return Convert.ChangeType (value, typeof (byte));
-                       case SqlDbType.Float:
-                               return Convert.ChangeType (value, typeof (Double));
-                       case SqlDbType.Real:
-                               return Convert.ChangeType (value, typeof (Single));
-                       case SqlDbType.Decimal:
-                               return Convert.ChangeType (value, typeof (Decimal));
+                       if (frameworkType == typeof (string)) {
+                               if (value is DateTime)
+                                       return ((DateTime) value).ToString ("yyyy-MM-dd'T'HH':'mm':'ss.fffffff");
+                               if (value is DateTimeOffset)
+                                       return ((DateTimeOffset) value).ToString ("yyyy-MM-dd'T'HH':'mm':'ss.fffffffzzz");
+                       }
+
+                       object sqlvalue = Convert.ChangeType (value, frameworkType);
+                       switch (sqlDbType) {
                        case SqlDbType.Money:
                        case SqlDbType.SmallMoney:
-                               {
-                                       Decimal val = (Decimal)Convert.ChangeType (value, typeof (Decimal));
-                                       return Decimal.Round(val, 4);
-                               }
-                       case SqlDbType.DateTime:
-                       case SqlDbType.SmallDateTime:
-                               return Convert.ChangeType (value, typeof (DateTime));
-                       case SqlDbType.VarChar:
-                       case SqlDbType.NVarChar:
-                       case SqlDbType.Char:
-                       case SqlDbType.NChar:
-                       case SqlDbType.Text:
-                       case SqlDbType.NText:
-#if NET_2_0
-                       case SqlDbType.Xml:
-#endif
-                               return Convert.ChangeType (value,  typeof (string));
-                       case SqlDbType.UniqueIdentifier:
-                               return Convert.ChangeType (value,  typeof (Guid));
-                       case SqlDbType.Variant:
-                               return metaParameter.Value;
+                               sqlvalue = Decimal.Round ((decimal) sqlvalue, 4);
+                               break;
                        }
-                       throw new  NotImplementedException ("Type Not Supported : " + sqlDbType.ToString());
+                       return sqlvalue;
                }
 
-#if NET_2_0
                public override void ResetDbType ()
                {
                        InferSqlType (Value);
@@ -1255,7 +1103,6 @@ namespace System.Data.SqlClient {
                {
                        InferSqlType (Value);
                }
-#endif // NET_2_0
 
                #endregion // Methods
        }