杨大奎» SQL Server CLR全功略之五—CLR自定义数据类型

一、这是这个系列的{zh1}一节了,自定义复杂数据类型目前只能通过CLR来实现。为了在 SQL Server 中运行,您的 UDT 必须实现 UDT 定义中的以下要求:

?

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

?

2.UDT 必须通过创建公共的 staticMicrosoft Visual Basic 中为 Shared)Null 方法,在类或结构中实现 System.Data.SqlTypes.INullable 接口。默认情况下,SQL Server 是可识别 Null 的。这是为使在 UDT 中执行的代码能够识别 Null 值所必需的。

?

3.UDT 必须包含支持从其进行分析的公共 static (或 SharedParse 方法以及用于转换到对象的字符串表示形式的 ToString 方法。

?

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

?

5. UDT 必须实现 System.Xml.Serialization.IXmlSerializable,或者所有公共字段和属性必须均属于 XML 可序列化类型或者使用 XmlIgnore 属性进行修饰(如果要求替代标准序列化)。

?

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

?

7.为了确保服务器将字节顺序的比较用于 UDT 值,SqlUserDefinedTypeAttribute.IsByteOrdered 必须为 true

?

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

?

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

?

10.公共名称不能长于 128 个字符,并且必须符合在标识符中定义的针对标识符的 SQL Server 命名规则。

?

11.sql_variant 列不能包含 UDT 的实例。

?

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

?

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

?

14.任何 static(或 Shared)成员都必须声明为常量或声明为只读。静态成员将无法改变。

?

15. SQL Server 2008 开始,如果 SqlUserDefinedTypeAttribute.MaxByteSize 字段设置为 -1,则序列化 UDT 在大小上可达到大对象 (LOB) 大小限制(目前为 2 GB)。该 UDT 的大小不能超过在 MaxByteSized 字段中指定的值。

?

?

?

二、下面的代码实现了坐标的自定义类型

?

view plaincopy to clipboardprint?

using System;??

using System.Collections.Generic;??

using System.Text;??

using Microsoft.SqlServer.Server;??

using System.Runtime.InteropServices;??

using System.Data.SqlTypes;??

?

[Serializable]??

[StructLayout(LayoutKind.Sequential)]??

[SqlUserDefinedType(Format.Native, IsByteOrdered = true)]??

public class UDT_Point : INullable??

{??

??? private int x;??

??? /// <summary>??

??? /// X坐标??

??? /// </summary>??

??? public int X??

??? {??

??????? get { return x; }??

??????? set { x = value; }??

??? }??

?

??? private int y;??

??? /// <summary>??

??? /// Y坐标??

??? /// </summary>??

??? public int Y??

??? {??

??????? get { return y; }??

??????? set { y = value; }??

??? }??

?

??? //是否为NULL标志??

??? private bool _isNull;??

??? public UDT_Point(int x, int y)??

??? {??

??????? this._isNull = true;??

??????? this.x = x;??

??????? this.y = y;??

??? }??

??? public UDT_Point()??

??? {??

??????? this._isNull = true;??

??????? this.x = this.y = 0;??

??? }??

??? /// <summary>??

??? /// 加法运算符??

??? /// </summary>??

??? /// <param name=”item”></param>??

??? /// <returns></returns>??

??? [SqlMethod(OnNullCall = false)]??

??? public UDT_Point Add(UDT_Point item)??

??? {??

??????? //被加数为空,直接返回this??

??????? if (item._isNull)??

??????????? return this;??

??????? return new UDT_Point(item.x + this.x, item.y + this.y);??

??? }??

??? /// <summary>??

??? /// 减法运算符??

??? /// </summary>??

??? /// <param name=”item”></param>??

??? /// <returns></returns>??

??? [SqlMethod(OnNullCall = false)]??

??? public UDT_Point Minus(UDT_Point item)??

??? {??

??????? //被减数为空,直接返回this??

??????? if (item._isNull)??

??????????? return this;??

??????? return new UDT_Point(this.x - item.x, this.y - item.y);??

??? }??

?

??? /// <summary>??

??? /// 解析函数。必须有??

??? /// </summary>??

??? /// <param name=”strString”></param>??

??? /// <returns></returns>??

??? public static UDT_Point Parse(SqlString strString)??

??? {??

??????? int x = int.Parse(strString.Value.Split(’,')[0]);??

??????? int y = int.Parse(strString.Value.Split(’,')[1]);??

??????? return new UDT_Point(x, y);??

??? }??

?

??? /// <summary>??

??? /// 为空处理,必须有??

??? /// </summary>??

??? public static UDT_Point Null??

??? {??

??????? get?

??????? {??

??????????? return new UDT_Point();??

??????? }??

??? }??

?

??? /// <summary>??

??? /// 显示函数,必须有??

??? /// </summary>??

??? /// <returns></returns>??

??? public override string ToString()??

??? {??

??????? return string.Format(”({0},{1})”, this.x, this.y);??

??? }?

?

??? #region INullable Members??

??? /// <summary>??

??? /// 实现为NULL接口??

??? /// </summary>??

??? public bool IsNull??

??? {??

??????? get { return this._isNull; }??

??????? set { this._isNull = true; }??

??? }?

??? #endregion??

}?

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SqlServer.Server;

using System.Runtime.InteropServices;

using System.Data.SqlTypes;

?

[Serializable]

[StructLayout(LayoutKind.Sequential)]

[SqlUserDefinedType(Format.Native, IsByteOrdered = true)]

public class UDT_Point : INullable

{

??? private int x;

??? /// <summary>

??? /// X坐标

??? /// </summary>

??? public int X

??? {

???? ???get { return x; }

??????? set { x = value; }

??? }

?

??? private int y;

??? /// <summary>

??? /// Y坐标

??? /// </summary>

??? public int Y

??? {

??????? get { return y; }

??????? set { y = value; }

??? }

?

??? //是否为NULL标志

??? private bool _isNull;

??? public UDT_Point(int x, int y)

??? {

??????? this._isNull = true;

??????? this.x = x;

??????? this.y = y;

??? }

??? public UDT_Point()

??? {

??????? this._isNull = true;

??????? this.x = this.y = 0;

??? }

??? /// <summary>

??? /// 加法运算符

??? /// </summary>

??? /// <param name=”item”></param>

??? /// <returns></returns>

??? [SqlMethod(OnNullCall = false)]

??? public UDT_Point Add(UDT_Point item)

??? {

??????? //被加数为空,直接返回this

??????? if (item._isNull)

??????????? return this;

??????? return new UDT_Point(item.x + this.x, item.y + this.y);

??? }

??? /// <summary>

??? /// 减法运算符

??? /// </summary>

??? /// <param name=”item”></param>

??? /// <returns></returns>

??? [SqlMethod(OnNullCall = false)]

??? public UDT_Point Minus(UDT_Point item)

??? {

??????? //被减数为空,直接返回this

??????? if (item._isNull)

??????????? return this;

??????? return new UDT_Point(this.x - item.x, this.y - item.y);

??? }

?

??? /// <summary>

??? /// 解析函数。必须有

??? /// </summary>

??? /// <param name=”strString”></param>

??? /// <returns></returns>

??? public static UDT_Point Parse(SqlString strString)

??? {

??????? int x = int.Parse(strString.Value.Split(’,')[0]);

??????? int y = int.Parse(strString.Value.Split(’,')[1]);

??????? return new UDT_Point(x, y);

??? }

?

??? /// <summary>

??? /// 为空处理,必须有

??? /// </summary>

??? public static UDT_Point Null

??? {

??????? get

??????? {

??????????? return new UDT_Point();

??????? }

??? }

?

??? /// <summary>

??? /// 显示函数,必须有

??? /// </summary>

??? /// <returns></returns>

??? public override string ToString()

??? {

?????? ?return string.Format(”({0},{1})”, this.x, this.y);

??? }

?

??? #region INullable Members

??? /// <summary>

??? /// 实现为NULL接口

??? /// </summary>

??? public bool IsNull

??? {

??????? get { return this._isNull; }

??????? set { this._isNull = true; }

??? }

?? ?#endregion

}

?

?

三、部署及调用SQL脚本

?

CREATE TYPE dbo.UDT_Point

EXTERNAL NAME CLRDemoAssemly.[UDT_Point];

?

评论审阅已启用。您的评论可能需要一段时间才会出现。

郑重声明:资讯 【杨大奎» SQL Server CLR全功略之五—CLR自定义数据类型】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——