用户定义的类型 (UDT) 要求

适用范围:SQL Server

创建要在 SQL Server 中安装的用户定义类型(UDT)时,必须做出几个重要的设计决策。 对于大多数 UDT,建议将 UDT 作为结构创建,尽管也可以选择将其作为类创建。 UDT 定义必须符合创建 UDT 的规范,以便将其注册到 SQL Server。

实现 UDT 的要求

若要在 SQL Server 中运行,UDT 必须在 UDT 定义中实现以下要求:

UDT 必须指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeSystem.SerializableAttribute 的使用是可选的,但建议使用。

  • UDT 必须通过创建公共 static(在 Visual Basic 中SharedNull 方法,在类或结构中实现 System.Data.SqlTypes.INullable 接口。 SQL Server 默认为 null 感知。 这是为使在 UDT 中执行的代码能够识别 Null 值所必需的。

  • UDT 必须包含支持分析的公共 static(或 SharedParse 方法,以及用于转换为对象的字符串表示形式的公共 ToString 方法。

  • 具有用户定义的序列化格式的 UDT 必须实现 System.Data.IBinarySerialize 接口,并提供 ReadWrite 方法。

  • UDT 必须实现 System.Xml.Serialization.IXmlSerializable,或者所有公共字段和属性必须是 XML 可序列化或修饰 XmlIgnore 属性的类型(如果需要重写标准序列化)。

  • 一个 UDT 对象必须只存在一个序列化。 如果序列化或反序列化例程识别了某一特定对象的多个表示形式,则验证将失败。

  • 必须 trueSqlUserDefinedTypeAttribute.IsByteOrdered 才能按字节顺序比较数据。 如果未实现 IComparable 接口并且 SqlUserDefinedTypeAttribute.IsByteOrderedfalse,则字节顺序比较会失败。

  • 在类中定义的 UDT 必须具有不采用任何参数的公共构造函数。 可以选择创建更多重载类构造函数。

  • 该 UDT 必须将数据元素作为公共字段或属性过程公开。

  • 公共名称不能超过 128 个字符,并且必须符合 数据库标识符中定义的标识符的 SQL Server 命名规则。

  • sql_variant 列不能包含 UDT 的实例。

  • 无法从 Transact-SQL 访问继承成员,因为 SQL Server 类型系统不知道 UDT 之间的继承层次结构。 但是,您可以在创建类的结构时使用继承,并且可以在该类型的托管代码实现方式中调用此类方法。

  • 成员不能重载,类构造函数除外。 如果确实创建了重载的方法,则注册程序集或在 SQL Server 中创建类型时不会引发错误。 在运行时将检测到重载的方法,而不是在创建类型时检测到。 只要从不调用重载方法,这些重载方法就可以存在于类中。 一旦您调用重载的方法,就会引发错误。

  • 任何 static(或 Shared)成员都必须声明为常量或只读成员。 静态成员不能可变。

  • 如果 SqlUserDefinedTypeAttribute.MaxByteSize 字段设置为 -1,则序列化的 UDT 可以像大型对象(LOB)大小限制(当前为 2 GB)一样大。 UDT 的大小不能超过 MaxByteSized 字段中指定的值。

注意

尽管服务器不使用它来执行比较,但可以选择实现 System.IComparable 接口,该接口公开单个方法 CompareTo。 在需要准确比较或排序 UDT 值的情况下,这在客户端上使用。

本机序列化

为 UDT 选择正确的序列化属性取决于要创建的 UDT 的类型。 Native 序列化格式利用一个简单的结构,使 SQL Server 能够在磁盘上存储 UDT 的有效本机表示形式。 如果 UDT 简单且仅包含以下类型的字段,则建议使用 Native 格式:

布尔字节字节ushortintuint乌龙浮点

由这些类型的字段组成的值类型非常适合用于 Native 格式,例如 C# 中的 struct 或 visual Basic .NET 中已知的 Structure。 例如,使用 Native 序列化格式指定的 UDT 可能包含另一个 UDT 的字段,该字段也使用 Native 格式指定。 如果 UDT 定义更为复杂,并且包含上一个列表中的数据类型,则必须改为指定 UserDefined 序列化格式。

Native 格式具有以下要求:

  • 类型不得为 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize指定值。

  • 所有字段必须均可序列化。

  • 如果在类中定义 UDT 而不是结构,则必须将 System.Runtime.InteropServices.StructLayoutAttribute 指定为 StructLayout.LayoutKindSequential。 此属性控制数据字段的物理布局,并用来按照成员的出现顺序对它们进行布局。 SQL Server 使用此属性来确定具有多个值的 UDT 的字段顺序。

有关使用 Native 序列化定义的 UDT 的示例,请参阅 创建具有 ADO.NET的用户定义类型中的 Point UDT。

用户定义的序列化

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 属性的 UserDefined 格式设置使开发人员可以完全控制二进制格式。 将 Format 属性指定为 UserDefined时,必须在代码中执行以下操作:

  • 指定可选的 IsByteOrdered 属性。 默认值为 false

  • 指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeMaxByteSize 属性。

  • 编写代码,通过实现 System.Data.Sql.IBinarySerialize 接口来实现 UDT 的 ReadWrite 方法。

有关使用 UserDefined 序列化定义的 UDT 的示例,请参阅 创建具有 ADO.NET的用户定义类型的货币 UDT。

注意

为了编制索引,UDT 字段必须使用本机序列化或者是持久化的。

序列化属性

属性确定如何使用序列化来构造 UDT 的存储表示形式以及如何按值将 UDT 传输到客户端。 创建 UDT 时需要指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeMicrosoft.SqlServer.Server.SqlUserDefinedTypeAttribute 属性指示该类是 UDT,并指定 UDT 的存储。 可以选择指定 Serializable 属性,尽管 SQL Server 不需要此属性。

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 具有以下属性。

格式

根据 UDT 的数据类型,指定可 NativeUserDefined的序列化格式。

IsByteOrdered

一个 Boolean 值,用于确定 SQL Server 如何对 UDT 执行二进制比较。

IsFixedLength

指示此 UDT 的所有实例是否都具有相同的长度。

MaxByteSize

实例的最大大小(以字节为单位)。 必须使用 UserDefined 序列化格式指定 MaxByteSize。 对于指定了用户定义的序列化的 UDT,MaxByteSize 是指 UDT 在其序列化形式(由用户定义)的总大小。 MaxByteSize 的值必须介于 18000范围内,或设置为 -1 以指示 UDT 大于 8,000 字节(总大小不能超过最大 LOB 大小)。 请考虑一个 UDT,其字符串属性为 10 个字符(System.Char)。 当使用 BinaryWriter 序列化 UDT 时,序列化字符串的总大小为 22 字节:每个 Unicode UTF-16 字符占 2 个字节,乘以最大字符数,再加上因序列化二进制流而导致的系统开销 2 个控制字节。 因此,确定 MaxByteSize的值时,必须考虑序列化 UDT 的总大小:以二进制形式序列化的数据的大小加上序列化产生的开销。

ValidationMethodName

用于验证 UDT 的实例的方法的名称。

Set isbyteordered

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered 属性设置为 true时,实际上可确保序列化的二进制数据可用于信息的语义排序。 因此,以字节排序的 UDT 对象的每个实例只能有一种序列化表示形式。 在 SQL Server 中对序列化字节执行比较操作时,其结果应与在托管代码中执行相同的比较操作相同。 当 IsByteOrdered 设置为 true时,还支持以下功能:

  • 可以对此类型的列创建索引。

  • 能够创建主键和外键,以及对此类型的列 CHECKUNIQUE 约束。

  • 能够使用 Transact-SQL ORDER BYGROUP BYPARTITION BY 子句。 此时,将使用该类型的二进制表示形式确定顺序。

  • 能够在 Transact-SQL 语句中使用比较运算符。

  • 可以保持此类型的计算列。

IsByteOrdered 设置为 true时,NativeUserDefined 序列化格式都支持以下比较运算符:

  • 等于 (=
  • 不等于 (!=
  • 大于号 (>)
  • 小于号 (<)
  • 大于或等于 (>=
  • 小于或等于 (<=

实现可为 null 性

除了正确指定程序集的属性外,类还必须支持为 Null 性。 加载到 SQL Server 中的 UDT 具有 null 感知性,但为了使 UDT 能够识别 null 值,类必须实现 INullable 接口。 有关如何在 UDT 中实现可为 null 性的详细信息和示例,请参阅 创建具有 ADO.NET的用户定义类型。

字符串转换

若要支持传入和传出 UDT 的字符串转换,必须在类中提供 Parse 方法和 ToString 方法。 Parse 方法允许将字符串转换为 UDT。 它必须声明为 static(或 Visual Basic 中的 Shared),并采用类型为 System.Data.SqlTypes.SqlString的参数。 有关如何实现 ParseToString 方法的详细信息和示例,请参阅 使用 ADO.NET创建用户定义的类型。

XML 序列化

UDT 必须支持通过符合 XML 序列化协定来回 转换 xml 数据类型。 System.Xml.Serialization 命名空间包含用于将对象序列化为 XML 格式文档或流的类。 可以选择使用 IXmlSerializable 接口实现 xml 序列化,该接口提供 XML 序列化和反序列化的自定义格式。

除了执行从 UDT 到 xml 的显式转换之外,XML 序列化还使您能够:

  • 在转换为 xml 数据类型后,对 UDT 实例的值使用 XQuery。

  • 在参数化查询和 Web 方法中使用 UDT 和 SQL Server 中的本机 XML Web 服务。

  • 使用 UDT 可以接收 XML 数据的大容量加载。

  • 序列化包含具有 UDT 列的表的数据集。

FOR XML 查询中不会序列化 UDT。 若要执行显示 UDT 的 XML 序列化的 FOR XML 查询,请显式将每个 UDT 列转换为 SELECT 语句中的 xml 数据类型。 还可以将列 显式转换为 varbinaryvarcharnvarchar