SQL-CLR 类型映射 (LINQ to SQL)

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

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

本主题讨论下列内容:

  • 默认类型映射

  • 类型映射运行时行为矩阵

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

  • 枚举映射

  • 数值映射

  • 文本和 XML 映射

  • 日期和时间映射

  • 二进制映射

  • 杂项映射

默认类型映射

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

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

类型映射运行时行为矩阵

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

注意注意

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

SQL 和 CLR 类型的映射

自定义类型映射

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

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 中,字符串比较行为取决于服务器上的排序规则设置。 有关更多信息,请参见 Microsoft“SQL Server 联机丛书”中的 Working with Collations(使用排序规则)。

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

枚举映射

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

  • 映射到 SQL 数值类型(TINYINT、SMALLINT、INT、BIGINT)

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

  • 映射到 SQL 文本类型(CHAR、NCHAR、VARCHAR、NVARCHAR)

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

注意注意

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

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

因为用于枚举的 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 Decimal 类型的精度小很多。 这可导致将数据保存到数据库时的精度降低。 但是,如果将 SQL Server DECIMAL 类型配置为大于 29 位精度,则会产生相反的结果。 将 SQL Server DECIMAL 类型的精度配置为大于 CLR System.Decimal 时,则在从数据库检索数据时会发生精度降低。

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

文本和 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 文本类型 (CHAR、 NCHAR、VARCHAR、NVARCHAR、TEXT、NTEXT、XML)。 通过将 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 类型 DATETIME2、DATETIMEOFFSET、DATE 和 TIME。从 .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 中得到充分支持的一种功能)的概念。 无论原始 DateTimeKind 信息如何,TimeZone 值均不进行 TimeZone 转换,按原样保存到数据库中。 从数据库中检索到 DateTime 值时,它们的值按原样加载到 DateTimeKindUnspecifiedDateTime 中。 有关受支持的 System.DateTime 方法的更多信息,请参见 System.DateTime 方法 (LINQ to SQL)

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 方法 (LINQ to SQL)

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

二进制映射

还有很多可以映射到 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 开始,提供了 VARBINARY(MAX) 列的 FILESTREAM 属性;从 .NET Framework 版本 3.5 SP1 开始,您可以使用 LINQ to SQL 映射到该属性。

尽管您可以使用 FILESTREAM 属性将 VARBINARY(MAX) 列映射到 Binary 对象,但是 DataContext.CreateDatabase 方法无法使用 FILESTREAM 属性自动创建列。 有关 FILESTREAM 的更多信息,请参见 Microsoft“SQL Server 联机丛书”中的 FILESTREAM Overview(FILESTREAM 概述)。

二进制序列化

如果一个类实现了 ISerializable 接口,则可以将对象序列化到任何 SQL 二进制字段 (BINARY、VARBINARY、IMAGE)。 将根据如何实现 ISerializable 接口来对对象进行序列化和反序列化。 有关更多信息,请参见 Binary Serialization(二进制序列化)。

杂项映射

下表显示一些尚未提及的杂项类型的默认类型映射。 下表显示生成基于数据库的对象模型或外部映射文件时 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 不支持这些杂项类型的任何其他类型映射。 有关更多信息,请参见类型映射运行时行为矩阵。

请参见

参考

基于属性的映射 (LINQ to SQL)

外部映射引用 (LINQ to SQL)

SQL-CLR 类型不匹配 (LINQ to SQL)

其他资源

数据类型和函数 (LINQ to SQL)