Подтвердить что ты не робот

Кто-нибудь получил функцию С#, которая сопоставляет тип данных SQL столбца с его эквивалентом CLR?

Я сижу, чтобы написать массивный оператор switch(), чтобы превратить типы данных SQL в типы данных CLR, чтобы генерировать классы из хранимых процедур MSSQL. Я использую эту диаграмму в качестве ссылки. Прежде чем я углубится в то, что, возможно, займет весь день и станет огромной болью, чтобы полностью протестировать, я хотел бы обратиться к сообществу SO, чтобы узнать, написал ли кто-нибудь еще что-либо на С#, чтобы выполнить это, казалось бы, общее и, безусловно, утомительная задача.

4b9b3361

Ответ 1

Это тот, который мы используем. Вы можете настроить его (например, типы с нулевым/непустым значением и т.д.), Но он должен сэкономить вам большую часть ввода.

public static Type GetClrType(SqlDbType sqlType)
{
    switch (sqlType)
    {
        case SqlDbType.BigInt:
            return typeof(long?);

        case SqlDbType.Binary:
        case SqlDbType.Image:
        case SqlDbType.Timestamp:
        case SqlDbType.VarBinary:
            return typeof(byte[]);

        case SqlDbType.Bit:
            return typeof(bool?);

        case SqlDbType.Char:
        case SqlDbType.NChar:
        case SqlDbType.NText:
        case SqlDbType.NVarChar:
        case SqlDbType.Text:
        case SqlDbType.VarChar:
        case SqlDbType.Xml:
            return typeof(string);

        case SqlDbType.DateTime:
        case SqlDbType.SmallDateTime:
        case SqlDbType.Date:
        case SqlDbType.Time:
        case SqlDbType.DateTime2:
            return typeof(DateTime?);

        case SqlDbType.Decimal:
        case SqlDbType.Money:
        case SqlDbType.SmallMoney:
            return typeof(decimal?);

        case SqlDbType.Float:
            return typeof(double?);

        case SqlDbType.Int:
            return typeof(int?);

        case SqlDbType.Real:
            return typeof(float?);

        case SqlDbType.UniqueIdentifier:
            return typeof(Guid?);

        case SqlDbType.SmallInt:
            return typeof(short?);

        case SqlDbType.TinyInt:
            return typeof(byte?);

        case SqlDbType.Variant:
        case SqlDbType.Udt:
            return typeof(object);

        case SqlDbType.Structured:
            return typeof(DataTable);

        case SqlDbType.DateTimeOffset:
            return typeof(DateTimeOffset?);

        default:
            throw new ArgumentOutOfRangeException("sqlType");
    }
}

Ответ 2

    /****** Object:  Table [dbo].[DbVsCSharpTypes]    Script Date: 03/20/2010 03:07:56 ******/
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DbVsCSharpTypes]') 
    AND type in (N'U'))
    DROP TABLE [dbo].[DbVsCSharpTypes]
    GO

    /****** Object:  Table [dbo].[DbVsCSharpTypes]    Script Date: 03/20/2010 03:07:56 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[DbVsCSharpTypes](
        [DbVsCSharpTypesId] [int] IDENTITY(1,1) NOT NULL,
        [Sql2008DataType] [varchar](200) NULL,
        [CSharpDataType] [varchar](200) NULL,
        [CLRDataType] [varchar](200) NULL,
        [CLRDataTypeSqlServer] [varchar](2000) NULL,

     CONSTRAINT [PK_DbVsCSharpTypes] PRIMARY KEY CLUSTERED 
    (
        [DbVsCSharpTypesId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO


    SET NOCOUNT ON;
    SET XACT_ABORT ON;
    GO

    SET IDENTITY_INSERT [dbo].[DbVsCSharpTypes] ON;
    BEGIN TRANSACTION;
    INSERT INTO [dbo].[DbVsCSharpTypes]([DbVsCSharpTypesId], [Sql2008DataType], [CSharpDataType], [CLRDataType], [CLRDataTypeSqlServer])
    SELECT 1, N'bigint', N'long', N'Int64, Nullable<Int64>', N'SqlInt64' UNION ALL
    SELECT 2, N'binary', N'byte[]', N'Byte[]', N'SqlBytes, SqlBinary' UNION ALL
    SELECT 3, N'bit', N'bool', N'Boolean, Nullable<Boolean>', N'SqlBoolean' UNION ALL
    SELECT 4, N'char', N'char', NULL, NULL UNION ALL
    SELECT 5, N'cursor', NULL, NULL, NULL UNION ALL
    SELECT 6, N'date', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL
    SELECT 7, N'datetime', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL
    SELECT 8, N'datetime2', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL
    SELECT 9, N'DATETIMEOFFSET', N'DateTimeOffset', N'DateTimeOffset', N'DateTimeOffset, Nullable<DateTimeOffset>' UNION ALL
    SELECT 10, N'decimal', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlDecimal' UNION ALL
    SELECT 11, N'float', N'double', N'Double, Nullable<Double>', N'SqlDouble' UNION ALL
    SELECT 12, N'geography', NULL, NULL, N'SqlGeography is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL
    SELECT 13, N'geometry', NULL, NULL, N'SqlGeometry is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL
    SELECT 14, N'hierarchyid', NULL, NULL, N'SqlHierarchyId is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL
    SELECT 15, N'image', NULL, NULL, NULL UNION ALL
    SELECT 16, N'int', N'int', N'Int32, Nullable<Int32>', N'SqlInt32' UNION ALL
    SELECT 17, N'money', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlMoney' UNION ALL
    SELECT 18, N'nchar', N'string', N'String, Char[]', N'SqlChars, SqlString' UNION ALL
    SELECT 19, N'ntext', NULL, NULL, NULL UNION ALL
    SELECT 20, N'numeric', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlDecimal' UNION ALL
    SELECT 21, N'nvarchar', N'string', N'String, Char[]', N'SqlChars, SqlStrinG SQLChars is a better match for data transfer and access, and SQLString is a better match for performing String operations.' UNION ALL
    SELECT 22, N'nvarchar(1), nchar(1)', N'string', N'Char, String, Char[], Nullable<char>', N'SqlChars, SqlString' UNION ALL
    SELECT 23, N'real', N'single', N'Single, Nullable<Single>', N'SqlSingle' UNION ALL
    SELECT 24, N'rowversion', N'byte[]', N'Byte[]', NULL UNION ALL
    SELECT 25, N'smallint', N'smallint', N'Int16, Nullable<Int16>', N'SqlInt16' UNION ALL
    SELECT 26, N'smallmoney', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlMoney' UNION ALL
    SELECT 27, N'sql_variant', N'object', N'Object', NULL UNION ALL
    SELECT 28, N'table', NULL, NULL, NULL UNION ALL
    SELECT 29, N'text', N'string', NULL, NULL UNION ALL
    SELECT 30, N'time', N'TimeSpan', N'TimeSpan, Nullable<TimeSpan>', N'TimeSpan' UNION ALL
    SELECT 31, N'timestamp', NULL, NULL, NULL UNION ALL
    SELECT 32, N'tinyint', N'byte', N'Byte, Nullable<Byte>', N'SqlByte' UNION ALL
    SELECT 33, N'uniqueidentifier', N'Guid', N'Guid, Nullable<Guid>', N'SqlGuidUser-defined type(UDT)The same class that is bound to the user-defined type in the same assembly or a dependent assembly.' UNION ALL
    SELECT 34, N'varbinary ', N'byte[]', N'Byte[]', N'SqlBytes, SqlBinary' UNION ALL
    SELECT 35, N'varbinary(1), binary(1)', N'byte', N'byte, Byte[], Nullable<byte>', N'SqlBytes, SqlBinary' UNION ALL
    SELECT 36, N'varchar', NULL, NULL, NULL UNION ALL
    SELECT 37, N'xml', NULL, NULL, N'SqlXml'
    COMMIT;
    RAISERROR (N'[dbo].[DbVsCSharpTypes]: Insert Batch: 1.....Done!', 10, 1) WITH NOWAIT;
    GO

    SET IDENTITY_INSERT [dbo].[DbVsCSharpTypes] OFF;

Ответ 3

    internal Type type(SqlDbType sqltype)
    {
        Type resulttype = null;
        Dictionary<SqlDbType, Type> Types = new Dictionary<SqlDbType, Type>();
        Types.Add(SqlDbType.BigInt, typeof(Int64));
        Types.Add(SqlDbType.Binary, typeof(Byte[]));
        Types.Add(SqlDbType.Bit, typeof(Boolean));
        Types.Add(SqlDbType.Char, typeof(String));
        Types.Add(SqlDbType.Date, typeof(DateTime));
        Types.Add(SqlDbType.DateTime, typeof(DateTime));
        Types.Add(SqlDbType.DateTime2, typeof(DateTime));
        Types.Add(SqlDbType.DateTimeOffset, typeof(DateTimeOffset));
        Types.Add(SqlDbType.Decimal, typeof(Decimal));
        Types.Add(SqlDbType.Float, typeof(Double));
        Types.Add(SqlDbType.Image, typeof(Byte[]));
        Types.Add(SqlDbType.Int, typeof(Int32));
        Types.Add(SqlDbType.Money, typeof(Decimal));
        Types.Add(SqlDbType.NChar, typeof(String));
        Types.Add(SqlDbType.NText, typeof(String));
        Types.Add(SqlDbType.NVarChar, typeof(String));
        Types.Add(SqlDbType.Real, typeof(Single));
        Types.Add(SqlDbType.SmallDateTime, typeof(DateTime));
        Types.Add(SqlDbType.SmallInt, typeof(Int16));
        Types.Add(SqlDbType.SmallMoney, typeof(Decimal));
        Types.Add(SqlDbType.Text, typeof(String));
        Types.Add(SqlDbType.Time, typeof(TimeSpan));
        Types.Add(SqlDbType.Timestamp, typeof(Byte[]));
        Types.Add(SqlDbType.TinyInt, typeof(Byte));
        Types.Add(SqlDbType.UniqueIdentifier, typeof(Guid));
        Types.Add(SqlDbType.VarBinary, typeof(Byte[]));
        Types.Add(SqlDbType.VarChar, typeof(String));
        Types.TryGetValue(sqltype, out resulttype);
        return resulttype;
    }

    internal SqlDbType type(Type systype)
    {
        SqlDbType resulttype = SqlDbType.NVarChar;
        Dictionary<Type, SqlDbType> Types = new Dictionary<Type, SqlDbType>();
        Types.Add(typeof(Boolean), SqlDbType.Bit);
        Types.Add(typeof(String), SqlDbType.NVarChar);
        Types.Add(typeof(DateTime), SqlDbType.DateTime);
        Types.Add(typeof(Int16), SqlDbType.Int);
        Types.Add(typeof(Int32), SqlDbType.Int);
        Types.Add(typeof(Int64), SqlDbType.Int);
        Types.Add(typeof(Decimal), SqlDbType.Float);
        Types.Add(typeof(Double), SqlDbType.Float);
        Types.TryGetValue(systype, out resulttype);
        return resulttype;
    }

Ответ 4

Вам не нужна функция. Я думаю, что вы можете искать

dt.Columns[i].DataType.UnderlyingSystemType

dt - dataTable

Это вернет тип CLR для соответствующего столбца. Надеюсь, это поможет, и BTW это мой первый ответ на стек переполнение

Ответ 5

Это не отвечает непосредственно на заданный вопрос, но отвечает на общий родственный вопрос. Когда у вас есть IDataReader, вы можете вызвать IDataRecord.GetFieldType(int), чтобы "[получить] Type информацию, соответствующую типу Object, который будет возвращен из GetValue."

Ответ 6

Я включаю это расширение (вы можете легко обменяться строковым ключом в словаре для SqlDbType, поскольку Greg реализовал или даже поддерживает оба) в моей модели и выставляет свойство, которое преобразует тип CLR:

    namespace X.Domain.Model
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        public class StoredProcedureParameter : DomainObject
        {
            public StoredProcedureParameter() { }

            public string StoredProcedure { get; set; }

            public string ProcedureSchema { get; set; }

            public string ProcedureName { get; set; }

            public string ParameterName { get; set; }

            public string ParameterOrder { get; set; }

            public string ParameterMode { get; set; }

            public string SqlDataType { get; set; }

            public Type DataType { get { return this.SqlDataType.ToClrType(); } }
        }

        static class StoredProcedureParameterExtensions
        {
            private static Dictionary<string, Type> Mappings;
            public static StoredProcedureParameterExtensions()
            {
                Mappings = new Dictionary<string, Type>();
                Mappings.Add("bigint", typeof(Int64));
                Mappings.Add("binary", typeof(Byte[]));
                Mappings.Add("bit", typeof(Boolean));
                Mappings.Add("char", typeof(String));
                Mappings.Add("date", typeof(DateTime));
                Mappings.Add("datetime", typeof(DateTime));
                Mappings.Add("datetime2", typeof(DateTime));
                Mappings.Add("datetimeoffset", typeof(DateTimeOffset));
                Mappings.Add("decimal", typeof(Decimal));
                Mappings.Add("float", typeof(Double));
                Mappings.Add("image", typeof(Byte[]));
                Mappings.Add("int", typeof(Int32));
                Mappings.Add("money", typeof(Decimal));
                Mappings.Add("nchar", typeof(String));
                Mappings.Add("ntext", typeof(String));
                Mappings.Add("numeric", typeof(Decimal));
                Mappings.Add("nvarchar", typeof(String));
                Mappings.Add("real", typeof(Single));
                Mappings.Add("rowversion", typeof(Byte[]));
                Mappings.Add("smalldatetime", typeof(DateTime));
                Mappings.Add("smallint", typeof(Int16));
                Mappings.Add("smallmoney", typeof(Decimal));
                Mappings.Add("text", typeof(String));
                Mappings.Add("time", typeof(TimeSpan));
                Mappings.Add("timestamp", typeof(Byte[]));
                Mappings.Add("tinyint", typeof(Byte));
                Mappings.Add("uniqueidentifier", typeof(Guid));
                Mappings.Add("varbinary", typeof(Byte[]));
                Mappings.Add("varchar", typeof(String));

            }

            public static Type ToClrType(this string sqlType)
            {
                Type datatype = null;
                if (Mappings.TryGetValue(sqlType, out datatype))
                    return datatype;
                throw new TypeLoadException(string.Format("Can not load CLR Type from {0}", sqlType));
            }
        }
    }

Ответ 7

Вы можете попробовать Wizardby. Однако он отображает от так называемых "родных" типов данных до DbType, которые затем тривиальны для преобразования в типы CLR. Если это подходит, вам понадобится соответствующий IDbTypeMapper - либо SqlServer2000TypeMapper, либо SqlServer2005TypeMapper.

Ответ 8

Здесь приведена ревизия, которая принимает значение NULL.

    public static Type GetClrType(SqlDbType sqlType, bool isNullable)
    {
        switch (sqlType)
        {
            case SqlDbType.BigInt:
                return isNullable ? typeof(long?) : typeof(long);

            case SqlDbType.Binary:
            case SqlDbType.Image:
            case SqlDbType.Timestamp:
            case SqlDbType.VarBinary:
                return typeof(byte[]);

            case SqlDbType.Bit:
                return isNullable ? typeof(bool?) : typeof(bool);

            case SqlDbType.Char:
            case SqlDbType.NChar:
            case SqlDbType.NText:
            case SqlDbType.NVarChar:
            case SqlDbType.Text:
            case SqlDbType.VarChar:
            case SqlDbType.Xml:
                return typeof(string);

            case SqlDbType.DateTime:
            case SqlDbType.SmallDateTime:
            case SqlDbType.Date:
            case SqlDbType.Time:
            case SqlDbType.DateTime2:
                return isNullable ? typeof(DateTime?) : typeof(DateTime);

            case SqlDbType.Decimal:
            case SqlDbType.Money:
            case SqlDbType.SmallMoney:
                return isNullable ? typeof(decimal?) : typeof(decimal);

            case SqlDbType.Float:
                return isNullable ? typeof(double?) : typeof(double);

            case SqlDbType.Int:
                return isNullable ? typeof(int?) : typeof(int);

            case SqlDbType.Real:
                return isNullable ? typeof(float?) : typeof(float);

            case SqlDbType.UniqueIdentifier:
                return isNullable ? typeof(Guid?) : typeof(Guid);

            case SqlDbType.SmallInt:
                return isNullable ? typeof(short?) : typeof(short);

            case SqlDbType.TinyInt:
                return isNullable ? typeof(byte?) : typeof(byte);

            case SqlDbType.Variant:
            case SqlDbType.Udt:
                return typeof(object);

            case SqlDbType.Structured:
                return typeof(DataTable);

            case SqlDbType.DateTimeOffset:
                return isNullable ? typeof(DateTimeOffset?) : typeof(DateTimeOffset);

            default:
                throw new ArgumentOutOfRangeException("sqlType");
        }
    }

Ответ 9

Я думаю, что для этого нет встроенного, но вы можете использовать VS для создания классов для своих таблиц, а затем попытаться отредактировать их

Ответ 10

Почему бы не создать типизированный набор данных и создать конструктор VS для вас? Если проект не должен адаптироваться во время выполнения к различным схемам, то вы должны использовать методы генерации кода для создания ваших классов, использовать встроенные конструкторы (например, типизированные наборы данных) или настраиваемые (schema- > XML- > XSLT- > . CS).

Ответ 11

Обычно я просто использую свойство Value для преобразования SqlType в собственный тип .NET. Это делает большую часть работы. Если у меня есть угловой случай, я просто напишу быструю вспомогательную функцию.

int i = dataReader.GetSqlInt32(0).Value;

Ответ 12

Я понимаю, что вы обсуждаете запись оператора switch, но здесь альтернатива для Sql Server (аналогичные концепции работают для других БД)

Рассмотрите возможность использования SysObjects для получения полных типов данных и создания вашего класса:

declare @ProcName varchar(255)
select @ProcName='Table, View, or Proc'
SELECT --DISTINCT 
    b.name 
    , c.name Type
    , b.xtype
    , b.length 
    , b.isoutparam
FROM 
    sysObjects a 
INNER JOIN sysCOLUMNs b ON a.id=b.id 
INNER JOIN systypes c ON b.xtype=c.xtype  
WHERE 
    [email protected]
order by b.colorder

Теперь вы просто перечисляете DataTable вместо более длинного оператора.