SQL Server CLR全功略之五---CLR自定义数据类型

来源:互联网 发布:电脑加速软件 编辑:程序博客网 时间:2024/06/05 04:42

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

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

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

3.UDT 必须包含支持从其进行分析的公共 static (或 Shared)Parse 方法以及用于转换到对象的字符串表示形式的 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 中注册程序集或创建类型时将不会引发错误。在运行时将检测到重载的方法,而不是在创建类型时检测到。只要永不调用重载的方法,重载的方法就可以存在于类中。一旦您调用重载的方法,就会引发错误。

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

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

 

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

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using Microsoft.SqlServer.Server;  
  5. using System.Runtime.InteropServices;  
  6. using System.Data.SqlTypes;  
  7.   
  8. [Serializable]  
  9. [StructLayout(LayoutKind.Sequential)]  
  10. [SqlUserDefinedType(Format.Native, IsByteOrdered = true)]  
  11. public class UDT_Point : INullable  
  12. {  
  13.     private int x;  
  14.     /// <summary>  
  15.     /// X坐标  
  16.     /// </summary>  
  17.     public int X  
  18.     {  
  19.         get { return x; }  
  20.         set { x = value; }  
  21.     }  
  22.   
  23.     private int y;  
  24.     /// <summary>  
  25.     /// Y坐标  
  26.     /// </summary>  
  27.     public int Y  
  28.     {  
  29.         get { return y; }  
  30.         set { y = value; }  
  31.     }  
  32.   
  33.     //是否为NULL标志  
  34.     private bool _isNull;  
  35.     public UDT_Point(int x, int y)  
  36.     {  
  37.         this._isNull = false;  
  38.         this.x = x;  
  39.         this.y = y;  
  40.     }  
  41.     public UDT_Point()  
  42.     {  
  43.         this._isNull = true;  
  44.         this.x = this.y = 0;  
  45.     }  
  46.     /// <summary>  
  47.     /// 加法运算符  
  48.     /// </summary>  
  49.     /// <param name="item"></param>  
  50.     /// <returns></returns>  
  51.     [SqlMethod(OnNullCall = false)]  
  52.     public UDT_Point Add(UDT_Point item)  
  53.     {  
  54.         //被加数为空,直接返回this  
  55.         if (item._isNull)  
  56.             return this;  
  57.         return new UDT_Point(item.x + this.x, item.y + this.y);  
  58.     }  
  59.     /// <summary>  
  60.     /// 减法运算符  
  61.     /// </summary>  
  62.     /// <param name="item"></param>  
  63.     /// <returns></returns>  
  64.     [SqlMethod(OnNullCall = false)]  
  65.     public UDT_Point Minus(UDT_Point item)  
  66.     {  
  67.         //被减数为空,直接返回this  
  68.         if (item._isNull)  
  69.             return this;  
  70.         return new UDT_Point(this.x - item.x, this.y - item.y);  
  71.     }  
  72.   
  73.     /// <summary>  
  74.     /// 解析函数。必须有  
  75.     /// </summary>  
  76.     /// <param name="strString"></param>  
  77.     /// <returns></returns>  
  78.     public static UDT_Point Parse(SqlString strString)  
  79.     {  
  80.         int x = int.Parse(strString.Value.Split(',')[0]);  
  81.         int y = int.Parse(strString.Value.Split(',')[1]);  
  82.         return new UDT_Point(x, y);  
  83.     }  
  84.   
  85.     /// <summary>  
  86.     /// 为空处理,必须有  
  87.     /// </summary>  
  88.     public static UDT_Point Null  
  89.     {  
  90.         get  
  91.         {  
  92.             return new UDT_Point();  
  93.         }  
  94.     }  
  95.   
  96.     /// <summary>  
  97.     /// 显示函数,必须有  
  98.     /// </summary>  
  99.     /// <returns></returns>  
  100.     public override string ToString()  
  101.     {  
  102.         return string.Format("({0},{1})"this.x, this.y);  
  103.     }  
  104.  
  105.     #region INullable Members  
  106.     /// <summary>  
  107.     /// 实现为NULL接口  
  108.     /// </summary>  
  109.     public bool IsNull  
  110.     {  
  111.         get { return this._isNull; }  
  112.         set { this._isNull = true; }  
  113.     }  
  114.     #endregion  
  115. }  
  

 

 

三、部署及调用SQL脚本

CREATE TYPE dbo.UDT_Point
EXTERNAL NAME CLRDemoAssemly.[UDT_Point];

 

 

CLR系列文章链接:
SQL Server CLR全功略之一---CLR介绍和配置:
http://blog.csdn.net/tjvictor/archive/2009/10/25/4726933.aspx

SQL Server CLR全功略之二---CLR存储过程:
http://blog.csdn.net/tjvictor/archive/2009/10/26/4731052.aspx

SQL Server CLR全功略之三---CLR标量函数、表值函数和聚合函数(UDA):
http://blog.csdn.net/tjvictor/archive/2009/11/10/4793781.aspx

SQL Server CLR全功略之四---CLR触发器:
http://blog.csdn.net/tjvictor/archive/2009/11/10/4795569.aspx

SQL Server CLR全功略之五---CLR自定义数据类型

http://blog.csdn.net/tjvictor/archive/2009/11/13/4807901.aspx

 

 

如需转载,请注明本文原创自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor