SqlProviderServices.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / SqlClient / SqlProviderServices.cs / 2 / SqlProviderServices.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//----------------------------------------------------------------------------- 
 
namespace System.Data.SqlClient {
 
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Data.Common.CommandTrees;
    using System.Data.Common.Utils; 
    using System.Data.Entity;
    using System.Data.Metadata.Edm; 
    using System.Data.Objects; 
    using System.Diagnostics;
    using System.IO; 
    using System.Reflection;
    using System.Xml;

    ///  
    /// The ProviderServices object for the SqlClient provider; we'll probably
    /// move this to the System.Data assembly once it can depend upon the extensions 
    /// assembly, and we'll make it public at that point. 
    /// 
    internal sealed class SqlProviderServices : DbProviderServices { 

        /// 
        /// Singleton object;
        ///  
        internal static readonly SqlProviderServices Instance = new SqlProviderServices();
 
        ///  
        /// Create a Command Definition object, given the connection and command tree
        ///  
        /// provider manifest that was determined from metadata
        /// command tree for the statement
        /// an exectable command definition object
        protected override DbCommandDefinition CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree) { 
            Debug.Assert(providerManifest != null, "CreateCommandDefinition passed null provider manifest to CreateDbCommandDefinition?");
            Debug.Assert(commandTree != null, "CreateCommandDefinition did not validate commandTree argument?"); 
 
            DbCommand prototype = CreateCommand(providerManifest, commandTree);
            DbCommandDefinition result = this.CreateCommandDefinition(prototype); 
            return result;
        }

        ///  
        /// Create a SqlCommand object given a command tree
        ///  
        /// command tree for the statement 
        /// a command object
        internal override DbCommand CreateCommand(DbCommandTree commandTree) { 
            EntityUtil.CheckArgumentNull(commandTree, "commandTree");
            StoreItemCollection storeMetadata = (StoreItemCollection)commandTree.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
            Debug.Assert(storeMetadata.StoreProviderManifest != null, "StoreItemCollection has null StoreProviderManifest?");
 
            return this.CreateCommand(storeMetadata.StoreProviderManifest, commandTree);
        } 
 
        /// 
        /// Create a SqlCommand object, given the provider manifest and command tree 
        /// 
        /// provider manifest
        /// command tree for the statement
        /// a command object 
        private DbCommand CreateCommand(DbProviderManifest providerManifest, DbCommandTree commandTree) {
            EntityUtil.CheckArgumentNull(providerManifest, "providerManifest"); 
            EntityUtil.CheckArgumentNull(commandTree, "commandTree"); 

            SqlProviderManifest sqlManifest = (providerManifest as SqlProviderManifest); 
            if (sqlManifest == null)
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Mapping_Provider_WrongManifestType(typeof(SqlProviderManifest)));
            } 

            SqlVersion sqlVersion = sqlManifest.SqlVersion; 
            SqlCommand command = new SqlCommand(); 

            EntityBid.Trace(" sqlVersion=%d commandTree=%d#\n", (int)sqlVersion, commandTree.ObjectId); 

            List parameters;
            CommandType commandType;
            command.CommandText = System.Data.SqlClient.SqlGen.SqlGenerator.GenerateSql(commandTree, sqlVersion, out parameters, out commandType); 
            command.CommandType = commandType;
            EntityBid.Trace(" Generated SQL=%s\n", command.CommandText); 
 
            // Get the function (if any) implemented by the command tree since this influences our interpretation of parameters
            EdmFunction function = null; 
            if (commandTree.CommandTreeKind == DbCommandTreeKind.Function) {
                function = ((DbFunctionCommandTree)commandTree).EdmFunction;
            }
            // Now make sure we populate the command's parameters from the CQT's parameters: 
            foreach (KeyValuePair queryParameter in commandTree.Parameters) {
                SqlParameter parameter; 
 
                // Use the corresponding function parameter TypeUsage where available (currently, the SSDL facets and
                // type trump user-defined facets and type in the EntityCommand). 
                FunctionParameter functionParameter;
                if (null != function && function.Parameters.TryGetValue(queryParameter.Key, false, out functionParameter)) {
                    const bool ignoreMaxLengthFacet = false;
                    parameter = CreateSqlParameter(functionParameter.Name, functionParameter.TypeUsage, functionParameter.Mode, DBNull.Value, ignoreMaxLengthFacet, sqlVersion); 
                }
                else { 
                    const bool ignoreMaxLengthFacet = false; 
                    parameter = CreateSqlParameter(queryParameter.Key, queryParameter.Value, ParameterMode.In, DBNull.Value, ignoreMaxLengthFacet, sqlVersion);
                } 
                command.Parameters.Add(parameter);
            }

            // Now add parameters added as part of SQL gen (note: this feature is only safe for DML SQL gen which 
            // does not support user parameters, where there is no risk of name collision)
            if (null != parameters && 0 < parameters.Count) { 
                if (commandTree.CommandTreeKind != DbCommandTreeKind.Delete && 
                    commandTree.CommandTreeKind != DbCommandTreeKind.Insert &&
                    commandTree.CommandTreeKind != DbCommandTreeKind.Update) { 
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.SqlGenParametersNotPermitted);
                }
                foreach (SqlParameter parameter in parameters) {
                    command.Parameters.Add(parameter); 
                }
            } 
 
            return command;
        } 

        protected override string GetDbProviderManifestToken(DbConnection connection) {
            EntityUtil.CheckArgumentNull(connection, "connection");
 
            SqlConnection sqlConnection = connection as SqlConnection;
            if (sqlConnection == null) { 
                throw EntityUtil.Argument(Strings.Mapping_Provider_WrongConnectionType(typeof(SqlConnection))); 
            }
 
            if (string.IsNullOrEmpty(sqlConnection.ConnectionString)) {
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            }
 
            bool closeConnection = false;
            try { 
                if (sqlConnection.State != ConnectionState.Open) { 
                    sqlConnection.Open();
                    closeConnection = true; 
                }
                SqlVersion version = SqlVersionUtils.GetSqlVersion(sqlConnection);
                return SqlVersionUtils.GetVersionHint(version);
            } 
            finally {
                if (closeConnection) { 
                    sqlConnection.Close(); 
                }
            } 
        }

        protected override DbProviderManifest GetDbProviderManifest(string versionHint) {
            if (string.IsNullOrEmpty(versionHint)) { 
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            } 
 
            return new SqlProviderManifest(versionHint);
        } 

        /// 
        /// Creates a SqlParameter given a name, type, and direction
        ///  
        internal static SqlParameter CreateSqlParameter(string name, TypeUsage type, ParameterMode mode, object value, bool ignoreMaxLengthFacet, SqlVersion version) {
            int? size; 
            byte? precision; 
            byte? scale;
 
            SqlParameter result = new SqlParameter(name, value);

            // .Direction
            ParameterDirection direction = MetadataHelper.ParameterModeToParameterDirection(mode); 
            if (result.Direction != direction) {
                result.Direction = direction; 
            } 

            // .Size, .Precision, .Scale and .SqlDbType 
            // output parameters are handled differently (we need to ensure there is space for return
            // values where the user has not given a specific Size/MaxLength)
            bool isOutParam = mode != ParameterMode.In;
            SqlDbType sqlDbType = GetSqlDbType(type, isOutParam, version, out size, out precision, out scale); 

            if (result.SqlDbType != sqlDbType) { 
                result.SqlDbType = sqlDbType; 
            }
 
            // Note that we overwrite 'facet' parameters where either the value is different or
            // there is an output parameter. This is because output parameters in SqlClient have their
            // facets clobbered if they are implicitly set (e.g. if the Precision was implicitly set
            // by setting the value) 
            if (!ignoreMaxLengthFacet && size.HasValue && (isOutParam || result.Size != size.Value)) {
                result.Size = size.Value; 
            } 
            if (precision.HasValue && (isOutParam || result.Precision != precision.Value)) {
                result.Precision = precision.Value; 
            }
            if (scale.HasValue && (isOutParam || result.Scale != scale.Value)) {
                result.Scale = scale.Value;
            } 

            // .IsNullable 
            bool isNullable = TypeSemantics.IsNullable(type); 
            if (isOutParam || isNullable != result.IsNullable) {
                result.IsNullable = isNullable; 
            }

            return result;
        } 

 
        ///  
        /// Determines SqlDbType for the given primitive type. Extracts facet
        /// information as well. 
        /// 
        private static SqlDbType GetSqlDbType(TypeUsage type, bool isOutParam, SqlVersion version, out int? size, out byte? precision, out byte? scale) {
            // only supported for primitive type
            PrimitiveTypeKind primitiveTypeKind = MetadataHelper.GetPrimitiveTypeKind(type); 

            size = default(int?); 
            precision = default(byte?); 
            scale = default(byte?);
 
            //
            switch (primitiveTypeKind) {
                case PrimitiveTypeKind.Binary:
                    // for output parameters, ensure there is space... 
                    size = GetParameterSize(type, isOutParam);
                    return GetBinaryDbType(type); 
 
                case PrimitiveTypeKind.Boolean:
                    return SqlDbType.Bit; 

                case PrimitiveTypeKind.Byte:
                    return SqlDbType.TinyInt;
 
                case PrimitiveTypeKind.Time:
                    if (!SqlVersionUtils.IsPreKatmai(version)) { 
                        precision = GetKatmaiDateTimePrecision(type, isOutParam); 
                    }
                    return SqlDbType.Time; 

                case PrimitiveTypeKind.DateTimeOffset:
                    if (!SqlVersionUtils.IsPreKatmai(version)) {
                        precision = GetKatmaiDateTimePrecision(type, isOutParam); 
                    }
                    return SqlDbType.DateTimeOffset; 
 
                case PrimitiveTypeKind.DateTime:
                    //For katmai pick the type with max precision which is datetime2 
                    if (!SqlVersionUtils.IsPreKatmai(version)) {
                        precision = GetKatmaiDateTimePrecision(type, isOutParam);
                        return SqlDbType.DateTime2;
                    } 
                    else {
                        return SqlDbType.DateTime; 
                    } 

                case PrimitiveTypeKind.Decimal: 
                    precision = GetParameterPrecision(type, null);
                    scale = GetScale(type);
                    return SqlDbType.Decimal;
 
                case PrimitiveTypeKind.Double:
                    return SqlDbType.Float; 
 
                case PrimitiveTypeKind.Guid:
                    return SqlDbType.UniqueIdentifier; 

                case PrimitiveTypeKind.Int16:
                    return SqlDbType.SmallInt;
 
                case PrimitiveTypeKind.Int32:
                    return SqlDbType.Int; 
 
                case PrimitiveTypeKind.Int64:
                    return SqlDbType.BigInt; 

                case PrimitiveTypeKind.SByte:
                    return SqlDbType.SmallInt;
 
                case PrimitiveTypeKind.Single:
                    return SqlDbType.Real; 
 
                case PrimitiveTypeKind.String:
                    size = GetParameterSize(type, isOutParam); 
                    return GetStringDbType(type);

                default:
                    Debug.Fail("unknown PrimitiveTypeKind " + primitiveTypeKind); 
                    return SqlDbType.Variant;
            } 
        } 

        ///  
        /// Determines preferred value for SqlParameter.Size. Returns null
        /// where there is no preference.
        /// 
        private static int? GetParameterSize(TypeUsage type, bool isOutParam) { 
            int maxLength;
            if (TypeHelpers.TryGetMaxLength(type, out maxLength)) { 
                // if the MaxLength facet has a specific value use it 
                return maxLength;
            } 
            else if (isOutParam) {
                // if the parameter is a return/out/inout parameter, ensure there
                // is space for any value
                return int.MaxValue; 
            }
            else { 
                // no value 
                return default(int?);
            } 
        }

        /// 
        /// Returns SqlParameter.Precision where the type facet exists. Otherwise, 
        /// returns null or the maximum available precision to avoid truncation (which can occur
        /// for output parameters). 
        ///  
        private static byte? GetKatmaiDateTimePrecision(TypeUsage type, bool isOutParam) {
            byte? defaultIfUndefined = isOutParam ? (byte?)7 : (byte?)null; 
            return GetParameterPrecision(type, defaultIfUndefined);
        }

        ///  
        /// Returns SqlParameter.Precision where the type facet exists. Otherwise,
        /// returns null. 
        ///  
        private static byte? GetParameterPrecision(TypeUsage type, byte? defaultIfUndefined) {
            byte precision; 
            if (TypeHelpers.TryGetPrecision(type, out precision)) {
                return precision;
            }
            else { 
                return defaultIfUndefined;
            } 
        } 

        ///  
        /// Returns SqlParameter.Scale where the type facet exists. Otherwise,
        /// returns null.
        /// 
        private static byte? GetScale(TypeUsage type) { 
            byte scale;
            if (TypeHelpers.TryGetScale(type, out scale)) { 
                return scale; 
            }
            else { 
                return default(byte?);
            }
        }
 
        /// 
        /// Chooses the appropriate SqlDbType for the given string type. 
        ///  
        private static SqlDbType GetStringDbType(TypeUsage type) {
            Debug.Assert(type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType && 
                PrimitiveTypeKind.String == ((PrimitiveType)type.EdmType).PrimitiveTypeKind, "only valid for string type");

            SqlDbType dbType;
            if (type.EdmType.Name.ToLowerInvariant() == "xml") { 
                dbType = SqlDbType.Xml;
            } 
            else { 
                // Specific type depends on whether the string is a unicode string and whether it is a fixed length string.
                // By default, assume widest type (unicode) and most common type (variable length) 
                bool unicode;
                bool fixedLength;
                if (!TypeHelpers.TryGetIsFixedLength(type, out fixedLength)) {
                    fixedLength = false; 
                }
 
                if (!TypeHelpers.TryGetIsUnicode(type, out unicode)) { 
                    unicode = true;
                } 

                if (fixedLength) {
                    dbType = (unicode ? SqlDbType.NChar : SqlDbType.Char);
                } 
                else {
                    dbType = (unicode ? SqlDbType.NVarChar : SqlDbType.VarChar); 
                } 
            }
            return dbType; 
        }

        /// 
        /// Chooses the appropriate SqlDbType for the given binary type. 
        /// 
        private static SqlDbType GetBinaryDbType(TypeUsage type) { 
            Debug.Assert(type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType && 
                PrimitiveTypeKind.Binary == ((PrimitiveType)type.EdmType).PrimitiveTypeKind, "only valid for binary type");
 
            // Specific type depends on whether the binary value is fixed length. By default, assume variable length.
            bool fixedLength;
            if (!TypeHelpers.TryGetIsFixedLength(type, out fixedLength)) {
                fixedLength = false; 
            }
 
            return fixedLength ? SqlDbType.Binary : SqlDbType.VarBinary; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//----------------------------------------------------------------------------- 
 
namespace System.Data.SqlClient {
 
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Data.Common.CommandTrees;
    using System.Data.Common.Utils; 
    using System.Data.Entity;
    using System.Data.Metadata.Edm; 
    using System.Data.Objects; 
    using System.Diagnostics;
    using System.IO; 
    using System.Reflection;
    using System.Xml;

    ///  
    /// The ProviderServices object for the SqlClient provider; we'll probably
    /// move this to the System.Data assembly once it can depend upon the extensions 
    /// assembly, and we'll make it public at that point. 
    /// 
    internal sealed class SqlProviderServices : DbProviderServices { 

        /// 
        /// Singleton object;
        ///  
        internal static readonly SqlProviderServices Instance = new SqlProviderServices();
 
        ///  
        /// Create a Command Definition object, given the connection and command tree
        ///  
        /// provider manifest that was determined from metadata
        /// command tree for the statement
        /// an exectable command definition object
        protected override DbCommandDefinition CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree) { 
            Debug.Assert(providerManifest != null, "CreateCommandDefinition passed null provider manifest to CreateDbCommandDefinition?");
            Debug.Assert(commandTree != null, "CreateCommandDefinition did not validate commandTree argument?"); 
 
            DbCommand prototype = CreateCommand(providerManifest, commandTree);
            DbCommandDefinition result = this.CreateCommandDefinition(prototype); 
            return result;
        }

        ///  
        /// Create a SqlCommand object given a command tree
        ///  
        /// command tree for the statement 
        /// a command object
        internal override DbCommand CreateCommand(DbCommandTree commandTree) { 
            EntityUtil.CheckArgumentNull(commandTree, "commandTree");
            StoreItemCollection storeMetadata = (StoreItemCollection)commandTree.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
            Debug.Assert(storeMetadata.StoreProviderManifest != null, "StoreItemCollection has null StoreProviderManifest?");
 
            return this.CreateCommand(storeMetadata.StoreProviderManifest, commandTree);
        } 
 
        /// 
        /// Create a SqlCommand object, given the provider manifest and command tree 
        /// 
        /// provider manifest
        /// command tree for the statement
        /// a command object 
        private DbCommand CreateCommand(DbProviderManifest providerManifest, DbCommandTree commandTree) {
            EntityUtil.CheckArgumentNull(providerManifest, "providerManifest"); 
            EntityUtil.CheckArgumentNull(commandTree, "commandTree"); 

            SqlProviderManifest sqlManifest = (providerManifest as SqlProviderManifest); 
            if (sqlManifest == null)
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Mapping_Provider_WrongManifestType(typeof(SqlProviderManifest)));
            } 

            SqlVersion sqlVersion = sqlManifest.SqlVersion; 
            SqlCommand command = new SqlCommand(); 

            EntityBid.Trace(" sqlVersion=%d commandTree=%d#\n", (int)sqlVersion, commandTree.ObjectId); 

            List parameters;
            CommandType commandType;
            command.CommandText = System.Data.SqlClient.SqlGen.SqlGenerator.GenerateSql(commandTree, sqlVersion, out parameters, out commandType); 
            command.CommandType = commandType;
            EntityBid.Trace(" Generated SQL=%s\n", command.CommandText); 
 
            // Get the function (if any) implemented by the command tree since this influences our interpretation of parameters
            EdmFunction function = null; 
            if (commandTree.CommandTreeKind == DbCommandTreeKind.Function) {
                function = ((DbFunctionCommandTree)commandTree).EdmFunction;
            }
            // Now make sure we populate the command's parameters from the CQT's parameters: 
            foreach (KeyValuePair queryParameter in commandTree.Parameters) {
                SqlParameter parameter; 
 
                // Use the corresponding function parameter TypeUsage where available (currently, the SSDL facets and
                // type trump user-defined facets and type in the EntityCommand). 
                FunctionParameter functionParameter;
                if (null != function && function.Parameters.TryGetValue(queryParameter.Key, false, out functionParameter)) {
                    const bool ignoreMaxLengthFacet = false;
                    parameter = CreateSqlParameter(functionParameter.Name, functionParameter.TypeUsage, functionParameter.Mode, DBNull.Value, ignoreMaxLengthFacet, sqlVersion); 
                }
                else { 
                    const bool ignoreMaxLengthFacet = false; 
                    parameter = CreateSqlParameter(queryParameter.Key, queryParameter.Value, ParameterMode.In, DBNull.Value, ignoreMaxLengthFacet, sqlVersion);
                } 
                command.Parameters.Add(parameter);
            }

            // Now add parameters added as part of SQL gen (note: this feature is only safe for DML SQL gen which 
            // does not support user parameters, where there is no risk of name collision)
            if (null != parameters && 0 < parameters.Count) { 
                if (commandTree.CommandTreeKind != DbCommandTreeKind.Delete && 
                    commandTree.CommandTreeKind != DbCommandTreeKind.Insert &&
                    commandTree.CommandTreeKind != DbCommandTreeKind.Update) { 
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.SqlGenParametersNotPermitted);
                }
                foreach (SqlParameter parameter in parameters) {
                    command.Parameters.Add(parameter); 
                }
            } 
 
            return command;
        } 

        protected override string GetDbProviderManifestToken(DbConnection connection) {
            EntityUtil.CheckArgumentNull(connection, "connection");
 
            SqlConnection sqlConnection = connection as SqlConnection;
            if (sqlConnection == null) { 
                throw EntityUtil.Argument(Strings.Mapping_Provider_WrongConnectionType(typeof(SqlConnection))); 
            }
 
            if (string.IsNullOrEmpty(sqlConnection.ConnectionString)) {
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            }
 
            bool closeConnection = false;
            try { 
                if (sqlConnection.State != ConnectionState.Open) { 
                    sqlConnection.Open();
                    closeConnection = true; 
                }
                SqlVersion version = SqlVersionUtils.GetSqlVersion(sqlConnection);
                return SqlVersionUtils.GetVersionHint(version);
            } 
            finally {
                if (closeConnection) { 
                    sqlConnection.Close(); 
                }
            } 
        }

        protected override DbProviderManifest GetDbProviderManifest(string versionHint) {
            if (string.IsNullOrEmpty(versionHint)) { 
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            } 
 
            return new SqlProviderManifest(versionHint);
        } 

        /// 
        /// Creates a SqlParameter given a name, type, and direction
        ///  
        internal static SqlParameter CreateSqlParameter(string name, TypeUsage type, ParameterMode mode, object value, bool ignoreMaxLengthFacet, SqlVersion version) {
            int? size; 
            byte? precision; 
            byte? scale;
 
            SqlParameter result = new SqlParameter(name, value);

            // .Direction
            ParameterDirection direction = MetadataHelper.ParameterModeToParameterDirection(mode); 
            if (result.Direction != direction) {
                result.Direction = direction; 
            } 

            // .Size, .Precision, .Scale and .SqlDbType 
            // output parameters are handled differently (we need to ensure there is space for return
            // values where the user has not given a specific Size/MaxLength)
            bool isOutParam = mode != ParameterMode.In;
            SqlDbType sqlDbType = GetSqlDbType(type, isOutParam, version, out size, out precision, out scale); 

            if (result.SqlDbType != sqlDbType) { 
                result.SqlDbType = sqlDbType; 
            }
 
            // Note that we overwrite 'facet' parameters where either the value is different or
            // there is an output parameter. This is because output parameters in SqlClient have their
            // facets clobbered if they are implicitly set (e.g. if the Precision was implicitly set
            // by setting the value) 
            if (!ignoreMaxLengthFacet && size.HasValue && (isOutParam || result.Size != size.Value)) {
                result.Size = size.Value; 
            } 
            if (precision.HasValue && (isOutParam || result.Precision != precision.Value)) {
                result.Precision = precision.Value; 
            }
            if (scale.HasValue && (isOutParam || result.Scale != scale.Value)) {
                result.Scale = scale.Value;
            } 

            // .IsNullable 
            bool isNullable = TypeSemantics.IsNullable(type); 
            if (isOutParam || isNullable != result.IsNullable) {
                result.IsNullable = isNullable; 
            }

            return result;
        } 

 
        ///  
        /// Determines SqlDbType for the given primitive type. Extracts facet
        /// information as well. 
        /// 
        private static SqlDbType GetSqlDbType(TypeUsage type, bool isOutParam, SqlVersion version, out int? size, out byte? precision, out byte? scale) {
            // only supported for primitive type
            PrimitiveTypeKind primitiveTypeKind = MetadataHelper.GetPrimitiveTypeKind(type); 

            size = default(int?); 
            precision = default(byte?); 
            scale = default(byte?);
 
            //
            switch (primitiveTypeKind) {
                case PrimitiveTypeKind.Binary:
                    // for output parameters, ensure there is space... 
                    size = GetParameterSize(type, isOutParam);
                    return GetBinaryDbType(type); 
 
                case PrimitiveTypeKind.Boolean:
                    return SqlDbType.Bit; 

                case PrimitiveTypeKind.Byte:
                    return SqlDbType.TinyInt;
 
                case PrimitiveTypeKind.Time:
                    if (!SqlVersionUtils.IsPreKatmai(version)) { 
                        precision = GetKatmaiDateTimePrecision(type, isOutParam); 
                    }
                    return SqlDbType.Time; 

                case PrimitiveTypeKind.DateTimeOffset:
                    if (!SqlVersionUtils.IsPreKatmai(version)) {
                        precision = GetKatmaiDateTimePrecision(type, isOutParam); 
                    }
                    return SqlDbType.DateTimeOffset; 
 
                case PrimitiveTypeKind.DateTime:
                    //For katmai pick the type with max precision which is datetime2 
                    if (!SqlVersionUtils.IsPreKatmai(version)) {
                        precision = GetKatmaiDateTimePrecision(type, isOutParam);
                        return SqlDbType.DateTime2;
                    } 
                    else {
                        return SqlDbType.DateTime; 
                    } 

                case PrimitiveTypeKind.Decimal: 
                    precision = GetParameterPrecision(type, null);
                    scale = GetScale(type);
                    return SqlDbType.Decimal;
 
                case PrimitiveTypeKind.Double:
                    return SqlDbType.Float; 
 
                case PrimitiveTypeKind.Guid:
                    return SqlDbType.UniqueIdentifier; 

                case PrimitiveTypeKind.Int16:
                    return SqlDbType.SmallInt;
 
                case PrimitiveTypeKind.Int32:
                    return SqlDbType.Int; 
 
                case PrimitiveTypeKind.Int64:
                    return SqlDbType.BigInt; 

                case PrimitiveTypeKind.SByte:
                    return SqlDbType.SmallInt;
 
                case PrimitiveTypeKind.Single:
                    return SqlDbType.Real; 
 
                case PrimitiveTypeKind.String:
                    size = GetParameterSize(type, isOutParam); 
                    return GetStringDbType(type);

                default:
                    Debug.Fail("unknown PrimitiveTypeKind " + primitiveTypeKind); 
                    return SqlDbType.Variant;
            } 
        } 

        ///  
        /// Determines preferred value for SqlParameter.Size. Returns null
        /// where there is no preference.
        /// 
        private static int? GetParameterSize(TypeUsage type, bool isOutParam) { 
            int maxLength;
            if (TypeHelpers.TryGetMaxLength(type, out maxLength)) { 
                // if the MaxLength facet has a specific value use it 
                return maxLength;
            } 
            else if (isOutParam) {
                // if the parameter is a return/out/inout parameter, ensure there
                // is space for any value
                return int.MaxValue; 
            }
            else { 
                // no value 
                return default(int?);
            } 
        }

        /// 
        /// Returns SqlParameter.Precision where the type facet exists. Otherwise, 
        /// returns null or the maximum available precision to avoid truncation (which can occur
        /// for output parameters). 
        ///  
        private static byte? GetKatmaiDateTimePrecision(TypeUsage type, bool isOutParam) {
            byte? defaultIfUndefined = isOutParam ? (byte?)7 : (byte?)null; 
            return GetParameterPrecision(type, defaultIfUndefined);
        }

        ///  
        /// Returns SqlParameter.Precision where the type facet exists. Otherwise,
        /// returns null. 
        ///  
        private static byte? GetParameterPrecision(TypeUsage type, byte? defaultIfUndefined) {
            byte precision; 
            if (TypeHelpers.TryGetPrecision(type, out precision)) {
                return precision;
            }
            else { 
                return defaultIfUndefined;
            } 
        } 

        ///  
        /// Returns SqlParameter.Scale where the type facet exists. Otherwise,
        /// returns null.
        /// 
        private static byte? GetScale(TypeUsage type) { 
            byte scale;
            if (TypeHelpers.TryGetScale(type, out scale)) { 
                return scale; 
            }
            else { 
                return default(byte?);
            }
        }
 
        /// 
        /// Chooses the appropriate SqlDbType for the given string type. 
        ///  
        private static SqlDbType GetStringDbType(TypeUsage type) {
            Debug.Assert(type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType && 
                PrimitiveTypeKind.String == ((PrimitiveType)type.EdmType).PrimitiveTypeKind, "only valid for string type");

            SqlDbType dbType;
            if (type.EdmType.Name.ToLowerInvariant() == "xml") { 
                dbType = SqlDbType.Xml;
            } 
            else { 
                // Specific type depends on whether the string is a unicode string and whether it is a fixed length string.
                // By default, assume widest type (unicode) and most common type (variable length) 
                bool unicode;
                bool fixedLength;
                if (!TypeHelpers.TryGetIsFixedLength(type, out fixedLength)) {
                    fixedLength = false; 
                }
 
                if (!TypeHelpers.TryGetIsUnicode(type, out unicode)) { 
                    unicode = true;
                } 

                if (fixedLength) {
                    dbType = (unicode ? SqlDbType.NChar : SqlDbType.Char);
                } 
                else {
                    dbType = (unicode ? SqlDbType.NVarChar : SqlDbType.VarChar); 
                } 
            }
            return dbType; 
        }

        /// 
        /// Chooses the appropriate SqlDbType for the given binary type. 
        /// 
        private static SqlDbType GetBinaryDbType(TypeUsage type) { 
            Debug.Assert(type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType && 
                PrimitiveTypeKind.Binary == ((PrimitiveType)type.EdmType).PrimitiveTypeKind, "only valid for binary type");
 
            // Specific type depends on whether the binary value is fixed length. By default, assume variable length.
            bool fixedLength;
            if (!TypeHelpers.TryGetIsFixedLength(type, out fixedLength)) {
                fixedLength = false; 
            }
 
            return fixedLength ? SqlDbType.Binary : SqlDbType.VarBinary; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK