【问题标题】:How to resolve System.Type to System.Data.DbType?如何将 System.Type 解析为 System.Data.DbType?
【发布时间】:2021-10-14 01:23:41
【问题描述】:

在 System 命名空间中查找基类库类型的 System.Data.DbType 枚举值的最佳方法是什么?

【问题讨论】:

    标签: c# .net ado.net


    【解决方案1】:

    一种常见的方法是使用类型映射,显式映射所有支持的类型(不同的连接器/提供者支持不同的类型)。这是Dapper 的类型映射:

    typeMap = new Dictionary<Type, DbType>();
    typeMap[typeof(byte)] = DbType.Byte;
    typeMap[typeof(sbyte)] = DbType.SByte;
    typeMap[typeof(short)] = DbType.Int16;
    typeMap[typeof(ushort)] = DbType.UInt16;
    typeMap[typeof(int)] = DbType.Int32;
    typeMap[typeof(uint)] = DbType.UInt32;
    typeMap[typeof(long)] = DbType.Int64;
    typeMap[typeof(ulong)] = DbType.UInt64;
    typeMap[typeof(float)] = DbType.Single;
    typeMap[typeof(double)] = DbType.Double;
    typeMap[typeof(decimal)] = DbType.Decimal;
    typeMap[typeof(bool)] = DbType.Boolean;
    typeMap[typeof(string)] = DbType.String;
    typeMap[typeof(char)] = DbType.StringFixedLength;
    typeMap[typeof(Guid)] = DbType.Guid;
    typeMap[typeof(DateTime)] = DbType.DateTime;
    typeMap[typeof(DateTimeOffset)] = DbType.DateTimeOffset;
    typeMap[typeof(byte[])] = DbType.Binary;
    typeMap[typeof(byte?)] = DbType.Byte;
    typeMap[typeof(sbyte?)] = DbType.SByte;
    typeMap[typeof(short?)] = DbType.Int16;
    typeMap[typeof(ushort?)] = DbType.UInt16;
    typeMap[typeof(int?)] = DbType.Int32;
    typeMap[typeof(uint?)] = DbType.UInt32;
    typeMap[typeof(long?)] = DbType.Int64;
    typeMap[typeof(ulong?)] = DbType.UInt64;
    typeMap[typeof(float?)] = DbType.Single;
    typeMap[typeof(double?)] = DbType.Double;
    typeMap[typeof(decimal?)] = DbType.Decimal;
    typeMap[typeof(bool?)] = DbType.Boolean;
    typeMap[typeof(char?)] = DbType.StringFixedLength;
    typeMap[typeof(Guid?)] = DbType.Guid;
    typeMap[typeof(DateTime?)] = DbType.DateTime;
    typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset;
    typeMap[typeof(System.Data.Linq.Binary)] = DbType.Binary;
    

    要获得相关的 DbType,您只需:

    var type = typeMap[typeof(string)]; // returns DbType.String
    

    【讨论】:

    • 这对我来说看起来不错。我认为 Nullable 版本不需要我,因为 Type.GetGenericTypeDefinitionType.GetGenericArguments 将有助于解决 Nullable 值和基础类型。
    【解决方案2】:

    您可以使用System.Web.UI.WebControls.Parameter 类中的ConvertTypeCodeToDbType 方法将TypeCode 转换为DbTypeParameter.ConvertTypeCodeToDbType Method。 要获取TypeCode,您可以使用方法Type.GetTypeCode(Type type)

    【讨论】:

    • 为什么这是System.Web
    【解决方案3】:

    您查看文档 - SQL Server Data Type Mappings (ADO.NET)

    其他提供者的映射也是documented

    这些为您提供了足够的信息来编写转换器。

    【讨论】:

    • 但是有没有提供者无关的方式?
    • @Mike - 我无法想象会有。不同的数据库和提供者以不同的方式实现。最接近您可以找到文档中最常见的映射并在公共类中使用它们。
    • 我明白了。我只是想知道为什么框架中有 DbType?它的值非常类似于 BCL 类型,所以我认为应该有一个默认映射。
    • @Mike - 没有默认映射。 DbType 尽可能代表所有数据库。
    【解决方案4】:

    我知道这是一个已经回答的老问题,但是使用SqlParameter 有更简单的方法,它已经实现了这个逻辑。 这是 SqlServer 特有的,但 PostgreMySql .. 等的提供程序都有相应的实现。

    这是一个完整的函数,它处理不可为空、可空的原始类型十进制字符串

    public static DbType GetDbType(Type runtimeType)
    {
        var nonNullableType = Nullable.GetUnderlyingType(runtimeType);
        if (nonNullableType != null)
        {
            runtimeType = nonNullableType;
        }
    
        var templateValue = (Object)null;
        if (runtimeType.IsClass == false)
        {
            templateValue = Activator.CreateInstance(runtimeType);
        }
    
        var sqlParamter = new SqlParameter(parameterName: String.Empty, value: templateValue);
    
        return sqlParamter.DbType;
    }
    

    如何获取SqlParameter:

    对于 SqlServer,根据您的 .netframework 版本,您可以在 System.DataSystem.Data.SqlClient nuget 中找到 SqlParamter 类型strong> 和 Microsoft.Data.SqlClient nuget


    SqlParameter源代码:

    SqlParameter 的实现使用了this piece of code,这与公认答案的提议非常接近。

    【讨论】:

    • 非常肮脏和低效,但非常聪明。
    【解决方案5】:

    我不知道有任何自动化逻辑,您应该自己进行映射,因为它们是不同的类型,而 .NET Framework 无法单独为您完成。

    在此处查看整个映射表:SQL Server Data Type Mappings (ADO.NET) 您可以想象对于 Oracle、MySQL、sqlite 和其他引擎,也可能有类似的表,也取决于 .NET 数据提供程序/连接

    【讨论】:

    【解决方案6】:

    我把这个留在这里,以防其他人碰巧需要 alexn 的答案中提到的 Dapper 查找表的倒数。 (它不会处理可空值)

    Dictionary<DbType, Type> dbTypeMap = new Dictionary<DbType, Type>()
    {
        { DbType.Binary, typeof(byte[])},
        { DbType.Boolean, typeof(bool)},
        { DbType.Byte, typeof(byte)},
        { DbType.DateTime, typeof(DateTime)},
        { DbType.DateTimeOffset, typeof(DateTimeOffset)},
        { DbType.Decimal, typeof(decimal)},
        { DbType.Double, typeof(double)},
        { DbType.Guid, typeof(Guid)},
        { DbType.Int16, typeof(short)},
        { DbType.Int32, typeof(int)},
        { DbType.Int64, typeof(long)},
        { DbType.SByte, typeof(sbyte)},
        { DbType.Single, typeof(float)},
        { DbType.String, typeof(string)},
        { DbType.StringFixedLength, typeof(char)},
        { DbType.UInt16, typeof(ushort)},
        { DbType.UInt32, typeof(uint)},
        { DbType.UInt64, typeof(ulong)}
    };
    

    【讨论】:

      猜你喜欢
      • 2017-06-19
      • 2011-01-23
      • 2015-09-20
      • 2010-09-10
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 2012-04-10
      相关资源
      最近更新 更多