【问题标题】:How can I programatically convert SQL data-types to .Net data-types?如何以编程方式将 SQL 数据类型转换为 .Net 数据类型?
【发布时间】:2011-01-30 02:39:21
【问题描述】:

谁能告诉我一种将 SQL Server 数据类型(例如 varchar)转换为 .Net 数据类型(例如 String)的方法。我假设自动转换是不可能的? 我有一个“EntityProperty”对象,并希望它有一个适当的“Type”属性(字符串、十进制、int32 等),目前该属性只是一个字符串 - 例如“int32”。

一点背景知识:我在内部代码生成应用程序中使用 SQL DMO 来查询数据库并从数据库生成基于存储过程的 DAL。作为一个内部应用程序,我可以走很多捷径并做出很多假设。为了让应用程序现在可以工作,这种数据类型转换由 Select Case 语句处理,该语句只是将类型转换为字符串并根据这些字符串生成一组属性,但我希望能够更灵活地处理类型(使用 TypeOf 等)。

有人做过类似的事情吗?

我知道 EF、nHibernate、Subsonic 等可以为我做这一切,但在这种情况下,由于各种原因,我不得不自己动手。 :)

【问题讨论】:

标签: .net sql-server code-generation


【解决方案1】:

硬编码是一件坏事的原因仅仅是因为当你把东西放在改变的代码中时,它很烦人(而且很昂贵)——没有其他原因。不会更改的内容(例如 pi 或工作日列表)可以硬编码为您喜欢的内容,因此您不会产生任何额外的开发成本。

所以这个问题与其说是不维护手动映射表(必要时在代码中),不如说是只在一个地方维护映射表。

几年前,我们推出了自己的数据访问类。当然,我们手动(在 VB.NET Select Case 语句中)将 .NET 类型转换为 SQL 类型。我认为它改变了一次,当我们不得不添加 Enum 类型时。

这是一次,大约在四年内。我们平均每周发布一次 - 猜猜我们对硬编码 .NET -> SQL 类型映射的“开销”有多担心?

在一个地方做。确保一切都使用它。然后忘记它。还有其他更棘手的问题需要解决。

【讨论】:

  • 我同意,我并不特别关心硬编码方面,我只是想知道我的 Select Case 方法是否遗漏了一些东西。 :)
【解决方案2】:

没有办法“自动”执行类型转换。事实上,大多数 ORM 库都依赖于目标实体类中使用的实际属性类型来执行映射。

我将使用 Linq to SQL 文档中的 SQL-CLR Type Mapping 作为构建手动映射代码的起点。在许多情况下,会有不止一个有效的映射。

【讨论】:

    【解决方案3】:

    我在另一个方向上做了类似的事情,使用 System.Type 对象的字典到 SQL 类型名称。

    【讨论】:

    • 这是我所拥有的,但我使用的是字符串而不是实际类型。
    【解决方案4】:

    或者您可以为您的自动翻译提供一个表格,然后使用这些值(这是一个初步的,没有经过大量测试......):

    USED IT DIRECTLY FOR CLASS GENERATION 或者即使你喜欢generate the classes for the whole db

            /****** 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'short', 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;
    

    【讨论】:

    • 每当我在数据库中看到 CLR 类型名称时,我都会感到畏缩。这是thedailywtf.com/Articles/Soft_Coding.aspx 的完美示例。
    • 取决于使用情况。这个有很多用途,其中之一是代码生成......
    • + 如果您有多供应商系统...例如使用一个 db 来配置不同的 RDBMS ....
    【解决方案5】:

    我知道 EF、nHibernate、Subsonic 等可以为我做这一切,但在这种情况下,由于各种原因,我不得不自己动手。 :)

    您为什么不使用 SubSonic 或其他 ORM 映射工具之一来定义 Sql 数据类型和 .Net 数据类型之间的工作转换 - 然后使用此转换信息作为基础推出您自己的解决方案?

    我假设您不能在解决方案中使用第三方软件 - 但您可以找到解决方案。

    【讨论】:

      猜你喜欢
      • 2020-10-22
      • 2014-10-09
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      • 2020-06-24
      • 1970-01-01
      相关资源
      最近更新 更多