SQL-CLR 类型映射

在 LINQ to SQL 中,关系数据库的数据模型映射到用您所选择的编程语言表示的对象模型。 当应用程序运行时,LINQ to SQL 会将对象模型中的语言集成查询转换为 SQL,然后将它们发送到数据库进行执行。 当数据库返回结果时,LINQ to SQL 会将它们转换回您可以用您自己的编程语言处理的对象。

要在对象模型和数据库之间转换数据,必须定义类型映射。 LINQ to SQL 使用类型映射将每个公共语言运行时 (CLR) 类型与一种特定 SQL Server 类型相匹配。 您可以使用基于属性的映射在对象模型内部定义类型映射和其他映射信息,例如数据库结构和表关系。 或者,您可以使用外部映射文件在对象模型外部指定映射信息。 有关详细信息,请参阅基于属性的映射外部映射

本主题讨论下列内容:

默认类型映射

您可以使用对象关系设计器(O/R 设计器)或 SQLMetal 命令行工具自动创建对象模型或外部映射文件。 这些工具的默认类型映射定义选择何种 CLR 类型来映射到 SQL Server 数据库内部的列。 有关这些工具用法的详细信息,请参阅创建对象模型

您也可以使用 CreateDatabase 方法来创建基于对象模型或外部映射文件中的映射信息的 SQL Server 数据库。 CreateDatabase 方法的默认类型映射定义创建何种 SQL Server 列来映射到对象模型中的 CLR 类型。 有关详细信息,请参阅如何:动态创建数据库

类型映射运行时行为矩阵

下图显示了数据从数据库检索或保存到数据库时特定类型映射的预期运行时行为。 除序列化之外,LINQ to SQL 不支持任何该矩阵中未指定的 CLR 或 SQL Server 数据类型之间的映射。 有关序列化支持的更多信息,请参见二进制序列化

SQL Server to SQL CLR data type mapping table

注意

在进行数据库转换时,某些类型映射可能会导致溢出或数据丢失异常。

自定义类型映射

通过使用 LINQ to SQL,您并非仅可以使用 O/R 设计器、SQLMetal 和 CreateDatabase 方法所使用的默认类型映射。 您可以通过在 DBML 文件中显式指定自定义类型映射来创建它们。 然后,可以使用该 DBML 文件创建对象模型代码和映射文件。 有关详细信息,请参阅 SQL-CLR 自定义类型映射

CLR 和 SQL 执行之间的行为差异

由于 CLR 和 SQL Server 之间的精度及执行差异,可能会收到不同的结果或体验不同的行为,这取决于执行计算的位置。 在 LINQ to SQL 查询中执行的计算实际上转换为 Transact-SQL,然后在 SQL Server 数据库上执行。 在 LINQ to SQL 查询外执行的计算则在 CLR 的上下文中执行。

例如,以下是一些 CLR 和 SQL Server 之间的行为差异:

  • SQL Server 对一些数据类型的排序不同于 CLR 中等效类型数据的排序。 例如,SQL Server 类型 UNIQUEIDENTIFIER 的数据排序不同于 CLR 类型 System.Guid 的数据排序。

  • SQL Server 处理一些字符串比较操作的方式不同于 CLR。 在 SQL Server 中,字符串比较行为取决于服务器上的排序规则设置。 有关详细信息,请参阅使用排序规则

  • 对于一些映射函数,SQL Server 返回的函数值可能与 CLR 不同。 例如,相等函数会不同,因为在两个字符串仅在尾随空白不同的情况下,SQL Server 会视这两个字符串相等,而 CLR 则视其不相等。

枚举映射

LINQ to SQL 支持使用如下两种方式将 CLR System.Enum 类型映射到 SQL Server 类型:

  • 映射到 SQL 数值类型(TINYINTSMALLINTINTBIGINT

    将 CLR System.Enum 类型映射到 SQL 数值类型时,您会将此 CLR System.Enum 的基础整数值映射到 SQL Server 数据库列的值。 例如,如果一个名为 System.EnumDaysOfWeek 包含一个名为 Tue 且基础整数值为 3 的成员,则此成员映射到数据库值 3。

  • 映射到 SQL 文本类型(CHARNCHARVARCHARNVARCHAR

    将 CLR System.Enum 类型映射到 SQL 文本类型时,SQL 数据库值会映射到 CLR System.Enum 成员的名称。 例如,如果一个名为 System.EnumDaysOfWeek 包含一个名为 Tue 且基础整数值为 3 的成员,则此成员映射到数据库值 Tue

备注

将 SQL 文本类型映射到 CLR System.Enum 时,映射的 SQL 列中仅包含 Enum 成员的名称。 Enum 映射的 SQL 列不支持其他值。

O/R 设计器和 SQLMetal 命令行工具无法将 SQL 类型自动映射到 CLR Enum 类。 您必须通过自定义 DBML 文件以供 O/R 设计器和 SQLMetal 使用来显式配置此映射。 有关自定义类型映射的详细信息,请参阅 SQL-CLR 自定义类型映射

因为用于枚举的 SQL 列将具有与其他数值和文本列相同的类型,所以这些工具无法识别你的意图,并会使用默认的映射,如下面的数值映射以及文本和 XML 映射部分所述。 有关使用 DBML 文件生成代码的详细信息,请参阅 LINQ to SQL 中的代码生成

DataContext.CreateDatabase 方法创建一个数值类型的 SQL 列以映射 CLR System.Enum 类型。

数值映射

LINQ to SQL 允许您映射多种 CLR 和 SQL Server 数值类型。 下表显示生成基于数据库的对象模型或外部映射文件时 O/R 设计器和 SQLMetal 选择的 CLR 类型。

SQL Server 类型 O/R 设计器和 SQLMetal 使用的默认 CLR 类型映射
BIT System.Boolean
TINYINT System.Int16
INT System.Int32
BIGINT System.Int64
SMALLMONEY System.Decimal
MONEY System.Decimal
DECIMAL System.Decimal
NUMERIC System.Decimal
REAL/FLOAT(24) System.Single
FLOAT/FLOAT(53) System.Double

下一个表显示 DataContext.CreateDatabase 方法使用的默认类型映射,以定义创建何种 SQL 列来映射到对象模型或外部映射文件中定义的 CLR 类型。

CLR 类型 DataContext.CreateDatabase 使用的默认 SQL Server 类型
System.Boolean BIT
System.Byte TINYINT
System.Int16 SMALLINT
System.Int32 INT
System.Int64 BIGINT
System.SByte SMALLINT
System.UInt16 INT
System.UInt32 BIGINT
System.UInt64 DECIMAL(20)
System.Decimal DECIMAL(29,4)
System.Single REAL
System.Double FLOAT

有许多其他可以选择的数值映射,但是某些数值映射在转换到数据库或从数据库中转换时,可能会导致溢出或数据丢失异常。 有关详细信息,请参见类型映射运行时行为矩阵

Decimal 和 Money 类型

SQL Server DECIMAL 类型的默认精度(小数点左边和右边取 18 个十进制位数)比默认配对的 CLR System.Decimal 类型的精度小很多。 这可导致将数据保存到数据库时的精度降低。 但是,如果将 SQL Server DECIMAL 类型配置为大于 29 位精度,则会产生相反的结果。 将 SQL Server DECIMAL 类型的精度配置为大于 CLR System.Decimal 时,则在从数据库检索数据时会发生精度降低。

默认情况下和 CLR MONEY 类型成对使用的 SQL Server SMALLMONEYSystem.Decimal 具有非常小的精度,在将数据保存到数据库时可导致溢出或数据丢失异常。

文本和 XML 映射

还有很多基于文本的类型和 XML 类型,您可以使用 LINQ to SQL 将其映射。 下表显示生成基于数据库的对象模型或外部映射文件时 O/R 设计器和 SQLMetal 选择的 CLR 类型。

SQL Server 类型 O/R 设计器和 SQLMetal 使用的默认 CLR 类型映射
CHAR System.String
NCHAR System.String
VARCHAR System.String
NVARCHAR System.String
TEXT System.String
NTEXT System.String
XML System.Xml.Linq.XElement

下一个表显示 DataContext.CreateDatabase 方法使用的默认类型映射,以定义创建何种 SQL 列来映射到对象模型或外部映射文件中定义的 CLR 类型。

CLR 类型 DataContext.CreateDatabase 使用的默认 SQL Server 类型
System.Char NCHAR(1)
System.String NVARCHAR(4000)
System.Char[] NVARCHAR(4000)
实现 Parse()ToString() 的自定义类型 NVARCHAR(MAX)

有许多其他可以选择的基于文本的映射和 XML 映射,但是某些映射在转换到数据库或从数据库中转换时,可能会导致溢出或数据丢失异常。 有关详细信息,请参见类型映射运行时行为矩阵

XML 类型

从 Microsoft SQL Server 2005 开始,提供了 SQL Server XML 数据类型。 您可以将 SQL Server XML 数据类型映射到 XElementXDocumentString。 如果列中存储了无法读入 XElement 的 XML 片段,则此列必须映射到 String 以免出现运行时错误。 必须映射到 String 的 XML 片段包括:

  • XML 元素的序列。

  • 特性

  • 公共标识符 (PI)

  • 注释

尽管你可以将 XElementXDocument 映射到 SQL Server(如类型映射运行时行为矩阵所示),但是 DataContext.CreateDatabase 方法没有针对这些类型的默认 SQL Server 类型映射。

自定义类型

如果一个类实现了 Parse()ToString(),则可以将对象映射到任何 SQL 文本类型(CHARNCHARVARCHARNVARCHARTEXTNTEXTXML)。 通过将 ToString() 返回的值发送到映射的数据库列,把对象存储在数据库中。 通过在数据库返回的字符串上调用 Parse() 重新构造对象。

备注

LINQ to SQL 不支持使用 System.Xml.Serialization.IXmlSerializable 进行序列化。

日期和时间映射

通过使用 LINQ to SQL,您可以映射多种 SQL Server 日期和时间类型。 下表显示生成基于数据库的对象模型或外部映射文件时 O/R 设计器和 SQLMetal 选择的 CLR 类型。

SQL Server 类型 O/R 设计器和 SQLMetal 使用的默认 CLR 类型映射
SMALLDATETIME System.DateTime
DATETIME System.DateTime
DATETIME2 System.DateTime
DATETIMEOFFSET System.DateTimeOffset
DATE System.DateTime
TIME System.TimeSpan

下一个表显示 DataContext.CreateDatabase 方法使用的默认类型映射,以定义创建何种 SQL 列来映射到对象模型或外部映射文件中定义的 CLR 类型。

CLR 类型 DataContext.CreateDatabase 使用的默认 SQL Server 类型
System.DateTime DATETIME
System.DateTimeOffset DATETIMEOFFSET
System.TimeSpan TIME

有许多其他可以选择的日期和时间映射,但是某些映射在转换到数据库或从数据库中转换时,可能会导致溢出或数据丢失异常。 有关详细信息,请参见类型映射运行时行为矩阵

备注

从 Microsoft SQL Server 2008 开始,提供了 SQL Server 类型 DATETIME2DATETIMEOFFSETDATETIME。 从 .NET Framework 版本 3.5 SP1 开始,LINQ to SQL 支持映射到这些新类型。

System.Datetime

CLR System.DateTime 类型的范围和精度大于 SQL Server DATETIME 类型,这是 DataContext.CreateDatabase 方法的默认类型映射。 要避免与 DATETIME 范围之外的日期相关的异常,请使用 DATETIME2(从 Microsoft SQL Server 2008 开始可用)。 DATETIME2 可以与 CLR System.DateTime 的范围和精度相匹配。

SQL Server 日期不具有 TimeZone(CLR 中得到充分支持的一种功能)的概念。 无论原始 TimeZone 信息如何,TimeZone 值均不进行 DateTimeKind 转换,按原样保存到数据库中。 从数据库中检索到 DateTime 值时,它们的值按原样加载到 DateTimeDateTimeKindUnspecified 中。 有关受支持的 System.DateTime 方法的详细信息,请参阅 System.DateTime 方法

System.TimeSpan

Microsoft SQL Server 2008 和 .NET Framework 3.5 SP1 允许您将 CLR System.TimeSpan 类型映射到 SQL Server TIME 类型。 但是,CLR System.TimeSpan 支持的范围和 SQL Server TIME 类型支持的范围之间存在很大的差异。 SQL TIME 的映射值小于 0 或大于 23:59:59.9999999 小时将导致溢出异常。 有关详细信息,请参阅 System.TimeSpan 方法

在 Microsoft SQL Server 2000 和 SQL Server 2005 中,您无法将数据库字段映射到 TimeSpan。 但是,支持对 TimeSpan 的操作,原因是可以通过 TimeSpan 减法运算返回 DateTime 值或将这些值作为文本或绑定变量引入表达式。

二进制映射

还有很多可以映射到 CLR 类型 System.Data.Linq.Binary 的 SQL Server 类型。 下表显示生成基于数据库的对象模型或外部映射文件时使 O/R 设计器和 SQLMetal 定义 CLR System.Data.Linq.Binary 类型的 SQL Server 类型。

SQL Server 类型 O/R 设计器和 SQLMetal 使用的默认 CLR 类型映射
BINARY(50) System.Data.Linq.Binary
VARBINARY(50) System.Data.Linq.Binary
VARBINARY(MAX) System.Data.Linq.Binary
具有 FILESTREAM 属性的 VARBINARY(MAX) System.Data.Linq.Binary
IMAGE System.Data.Linq.Binary
TIMESTAMP System.Data.Linq.Binary

下一个表显示 DataContext.CreateDatabase 方法使用的默认类型映射,以定义创建何种 SQL 列来映射到对象模型或外部映射文件中定义的 CLR 类型。

CLR 类型 DataContext.CreateDatabase 使用的默认 SQL Server 类型
System.Data.Linq.Binary VARBINARY(MAX)
System.Byte VARBINARY(MAX)
System.Runtime.Serialization.ISerializable VARBINARY(MAX)

有许多其他可以选择的二进制映射,但是某些映射在转换到数据库或从数据库中转换时,可能会导致溢出或数据丢失异常。 有关详细信息,请参见类型映射运行时行为矩阵

SQL Server FILESTREAM

从 Microsoft SQL Server 2008 开始,提供了 FILESTREAM 列的 VARBINARY(MAX) 属性;从 .NET Framework 版本 3.5 SP1 开始,您可以使用 LINQ to SQL 映射到该属性。

尽管您可以使用 VARBINARY(MAX) 属性将 FILESTREAM 列映射到 Binary 对象,但是 DataContext.CreateDatabase 方法无法使用 FILESTREAM 属性自动创建列。 有关 FILESTREAM 的详细信息,请参阅文件流概述

二进制序列化

如果一个类实现了 ISerializable 接口,则可以将对象序列化到任何 SQL 二进制字段 (BINARYVARBINARYIMAGE)。 将根据如何实现 ISerializable 接口来对对象进行序列化和反序列化。 有关详细信息,请参阅二进制序列化

杂项映射

下表显示一些尚未提及的杂项类型的默认类型映射。 下表显示生成基于数据库的对象模型或外部映射文件时 O/R 设计器和 SQLMetal 选择的 CLR 类型。

SQL Server 类型 O/R 设计器和 SQLMetal 使用的默认 CLR 类型映射
UNIQUEIDENTIFIER System.Guid
SQL_VARIANT System.Object

下一个表显示 DataContext.CreateDatabase 方法使用的默认类型映射,以定义创建何种 SQL 列来映射到对象模型或外部映射文件中定义的 CLR 类型。

CLR 类型 DataContext.CreateDatabase 使用的默认 SQL Server 类型
System.Guid UNIQUEIDENTIFIER
System.Object SQL_VARIANT

LINQ to SQL 不支持这些杂项类型的任何其他类型映射。 有关详细信息,请参见类型映射运行时行为矩阵

请参阅