创建用户定义类型 - 需求

适用于:SQL Server

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

实现 UDT 的要求

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 任何 静态 (或 共享)成员都必须声明为常量或只读成员。 静态成员将无法改变。

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

注意

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

本机序列化

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

boolbytesbyte, short, ushortintuintlong, ulongfloat, doubleSqlByte, SqlInt16, SqlInt32SqlInt64SqlDateTime, SqlSingleSqlDouble, SqlMoneySqlBoolean

由上述类型的字段组成的值类型非常适合本机格式,例如 Visual C# 中的结构(或 Visual Basic 中已知的结构)。 例如,使用本机序列化格式指定的 UDT 可能包含使用本机格式指定的另一个 UDT 的字段。 如果 UDT 定义更为复杂,并且包含不在上述列表中的数据类型,则必须改为指定 用户定义的 序列化格式。

本机格式具有以下要求:

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

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

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

有关使用本机序列化定义的 UDT 的示例,请参阅编码用户定义类型的点 UDT

UserDefined 序列化

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

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

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

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

有关使用用户定义的序列化定义的 UDT 的示例,请参阅编码用户定义类型中的 Currency UDT。

注意

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

序列化特性

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

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

Format
根据 UDT 的数据类型,指定序列化格式(可以是 本机 格式或 用户定义格式)。

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

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

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

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

设置 IsByteOrdered

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

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

  • 可以对此类型的列创建主键和外键以及 CHECK 和 UNIQUE 约束。

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

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

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

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

  • 等于(=)

  • 不等于 (!=)

  • 大于号 (>)

  • 小于号 (<)

  • 大于或等于 (>=)

  • 小于或等于 (<=)

实现为 Null 性

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

字符串转换

若要支持与 UDT 进行字符串转换,必须在类中提供 Parse 方法和 ToString 方法。 Parse 方法允许将字符串转换为 UDT。 它必须声明为静态(或在 Visual Basic 中共享),并采用 System.Data.SqlTypes.SqlString 类型的参数。 有关如何实现 Parse 和 ToString 方法的详细信息和示例,请参阅编码用户定义类型

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 列的表的数据集。

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

另请参阅

创建用户定义类型