【问题标题】:Given a T-SQL type as a string, what is the easiest way to evaluate it to a .Net Type?给定 T-SQL 类型作为字符串,将其评估为 .Net 类型的最简单方法是什么?
【发布时间】:2013-08-15 14:02:51
【问题描述】:

如果给定一个包含 SQL Server/T-SQL 数据类型的字符串,将字符串评估为 .Net 类型的最简单方法是什么?

例如,如果您有一个包含“nvarchar”的字符串,则转换方法返回的结果应该是System.String 类型。如果我有一个包含“int”的字符串,结果应该是一个System.Int32 Type 对象。

我可以轻松编写一个函数,该函数接受一个 SQL 数据类型字符串,并通过一个返回 .Net Type 对象的 switch/case 语句发送该字符串。但是,我不确定 .Net 框架中是否有一个我忽略的函数已经这样做了。

将 SQL Server 数据类型解析为 .Net 数据类型的最简单/正确的方法是什么?

附加上下文

在我的例子中,我实际上有一个存储过程,它返回一些关于数据的元信息。具体来说,返回一个字符串字段,其中包含一个 sql-type 值,该值可以是 SQL Server 2005 中可用的任何 sql-type。

我的存储过程有可能返回任何 sql 类型——intsmallintdatetimebinary 等。我需要采用这种数据类型并将其转换为 .Net @ 987654328@ 对象。

下面 Matthew 的评论确实提供了所有必要的映射信息,直接来自 Microsoft 的文档,但我再次想知道 System.DataSystem.Data.SqlClient 命名空间中是否集成了一些东西。

【问题讨论】:

  • 如果一个字符串包含来自 SQL 的一些数据,那么该数据当前是一个字符串。也许一些上下文会有所帮助。
  • 就像@Matthew 所说,SQL-CLR 类型映射是您所需要的。
  • 不太确定你打算在 .NET 中用它做什么。将其简单地存储在 var 中对您的目的不起作用吗?
  • @Ellesedil:如果建议将从 SQL 返回的数据存储为var,那不是我工作的重点。就我而言,我需要知道如何处理将插入(或更新)到数据表中的数据。如果我没有任何要评估的数据,我就无法导出正确的数据类型以存储在我的数据库中。具体来说,如果您从 SQL Server 获得空值,.Net 会将空值转换为 DBNull 对象,这不会告诉我有关基础列定义的任何信息。

标签: c# .net tsql types


【解决方案1】:

据我所知,没有任何暴露。在 System.Data.SqlClient 代码的深处有这个函数用于确定类型映射:

internal Type GetTypeFromStorageType(bool isSqlType)
{
    if (isSqlType)
    {
        switch (this._type)
        {
            case StorageType.Empty:
                return null;

            case StorageType.Boolean:
                return typeof(SqlBoolean);

            case StorageType.Byte:
                return typeof(SqlByte);

            case StorageType.DateTime:
                return typeof(SqlDateTime);

            case StorageType.Decimal:
                return typeof(SqlDecimal);

            case StorageType.Double:
                return typeof(SqlDouble);

            case StorageType.Int16:
                return typeof(SqlInt16);

            case StorageType.Int32:
                return typeof(SqlInt32);

            case StorageType.Int64:
                return typeof(SqlInt64);

            case StorageType.Money:
                return typeof(SqlMoney);

            case StorageType.Single:
                return typeof(SqlSingle);

            case StorageType.String:
                return typeof(SqlString);

            case StorageType.SqlBinary:
                return typeof(object);

            case StorageType.SqlCachedBuffer:
                return typeof(SqlString);

            case StorageType.SqlGuid:
                return typeof(object);

            case StorageType.SqlXml:
                return typeof(SqlXml);
        }
    }
    else
    {
        switch (this._type)
        {
            case StorageType.Empty:
                return null;

            case StorageType.Boolean:
                return typeof(bool);

            case StorageType.Byte:
                return typeof(byte);

            case StorageType.DateTime:
                return typeof(DateTime);

            case StorageType.Decimal:
                return typeof(decimal);

            case StorageType.Double:
                return typeof(double);

            case StorageType.Int16:
                return typeof(short);

            case StorageType.Int32:
                return typeof(int);

            case StorageType.Int64:
                return typeof(long);

            case StorageType.Money:
                return typeof(decimal);

            case StorageType.Single:
                return typeof(float);

            case StorageType.String:
                return typeof(string);

            case StorageType.SqlBinary:
                return typeof(byte[]);

            case StorageType.SqlCachedBuffer:
                return typeof(string);

            case StorageType.SqlGuid:
                return typeof(Guid);

            case StorageType.SqlXml:
                return typeof(string);
        }
    }
    return null;
}

【讨论】:

  • 是的,这就是我怀疑找到的东西。我不怕长 case 语句,事实上,它可能对我更有利,因为我可以覆盖某些类型。尽管如此,我还是更喜欢集成解决方案,如果有的话,因为这种操作很容易“错过”某些东西,这在处理关键数据时可能会产生可怕的后果。您会得到 +1,几天后,如果没有更好的答案,可能是答案标记。
【解决方案2】:

试试下面的功能。我相信您可以根据自己的需要进行调整。如果遗漏了什么,你会得到异常:

    public static Type SqlTypeToType(string type)
    {
        string[] tokens = type.Split(new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
        string typeFamily = tokens[0].ToLowerInvariant();
        string size = tokens.Length > 1 ? tokens[1] : string.Empty;

        switch (typeFamily)
        {
            case "bigint":
                return typeof(long);
            case "binary":
                return size == "1" ? typeof(byte) : typeof(byte[]);
            case "bit":
                return typeof(bool);
            case "char":
                return size == "1" ? typeof(char) : typeof(string);
            case "datetime":
                return typeof(DateTime);
            case "datetime2":
                return typeof(DateTime);
            case "decimal":
                return typeof(decimal);
            case "float":
                return typeof(double);
            case "image":
                return typeof(byte[]);
            case "int":
                return typeof(int);
            case "money":
                return typeof(decimal);
            case "nchar":
                return size == "1" ? typeof(char) : typeof(string);
            case "ntext":
                return typeof(string);
            case "nvarchar":
                return typeof(string);
            case "real":
                return typeof(float);
            case "uniqueidentifier":
                return typeof(Guid);
            case "smalldatetime":
                return typeof(DateTime);
            case "smallint":
                return typeof(short);
            case "smallmoney":
                return typeof(decimal);
            case "sql_variant":
                return typeof(object);
            case "text":
                return typeof(string);
            case "time":
                return typeof(TimeSpan);
            case "tinyint":
                return typeof(byte);
            case "varbinary":
                return typeof(byte[]);
            case "varchar":
                return typeof(string);
            case "variant":
                return typeof(string);
            case "xml":
                return typeof(string);
            default:
                throw new ArgumentException(string.Format("There is no .Net type specified for mapping T-SQL type '{0}'.", type));
        }
    }

【讨论】:

  • 哎呀,不要用这个。将money & smallmoney 映射为双倍?这很危险。
  • @reedparkes,你有什么建议?十进制?
  • @i-one:是的,我认为你应该使用小数来表示货币类型。 This is a useful reference 帮助查看实体框架使用的类型。尽管它会转换为自己的类型,但很清楚它们代表了哪些 C# 类型。不管怎样,谢谢你帮我省了打字!
猜你喜欢
  • 2022-01-25
  • 2012-03-03
  • 2016-11-26
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2012-01-07
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多