SQL2005 用户自定义类型
2010-04-20 16:05 calm_水手 阅读(1041) 评论(0) 编辑 收藏 举报之前对这个“用户自定义类型”只是有所耳闻,没有机会用过,也没有自己动手去写过。今天朋友让我写一个简单的“用户自定义类型”,呵呵,糗了。
下面是目前对它的了解。
在VS2008中新建项目选择“数据库”—“SQL Server项目”,上面的combobox选择".NET Framework2.0"
输入项目名称,选择好自己的项目所在文件夹,点解确认后,会提示:
选择要使用“用户自定义类型”的数据库,在“添加新引用”中找到目标数据库,点击“确定”即可。
进入项目后,在解决方案上“右键”—“添加”—“用户定义的类型”。如图所示
在这里面可以添加“用户定义的函数”、“存储过程”、“聚合”、“触发器”等。选择“用户定义的类型”,后便可看到可以编辑的代码层。
下面,在进行编码前,我们来了解一些内容,呵呵,这些内容,也是我边做边查的。呵呵,很庆幸,碰到不会的东西,能查一查,问一问,呵呵,也是件很好的事情。
1.实现“用户定义的类型”UDT的要求:
这个对应的就是上面的代码 public struct TypeTest:INullable。需要实现Null性,对null性的处理,是在这里处理的。
2 {
3 get
4 {
5 TypeTest h = new TypeTest();
6 h.m_Null = true;
7 return h;
8 }
9 }
必须创建一个名为 IsNull 的属性,在从 CLR 代码中确定值是否为空值时,需要使用该属性。SQL Server 发现 UDT 的空值实例时,将使用正常的空值处理方法保持该实例。服务器不会将时间浪费在序列化或反序列化 UDT 上(如果不是必须),也不会将空间浪费在存储空值 UDT 上。这种空值检查在每次从 CLR 引入 UDT 时执行,这意味着始终可以使用 Transact-SQL IS NULL 结构检查空值 UDT。服务器也使用 IsNull 属性来测试实例是否为空值。服务器确定 UDT 为空值后,可以使用其本机空值处理方法。
该方法的处理,是在这段代码中进行处理的:
2 {
3 // 用您的代码替换下列代码
4 return "";
5 }
具有用户定义序列化格式的 UDT 必须实现 System.Data.IBinarySerialize 接口并提供 Read 和 Write 方法。
对Read和Write方法的实现是在实现接口IBinarySerialize时需要处理的。处理方法如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 public string result;
3
4 public void Read(System.IO.BinaryReader r)
5 {
6
7 this.result = r.ReadString();
8 }
9
10 public void Write(System.IO.BinaryWriter w)
11 {
12
13 w.Write(this.result);
14 }
这段代码需要自己手动的写上去,实现Read和Write方法。
下面是编写用户自定义类型的其他要求:
编写用户类型的本地序列化:
为 UDT 选择正确的序列化属性取决于您正尝试创建的 UDT 的类型。 Native 序列化格式利用了一个非常简单的结构,使 SQL Server 能够在磁盘上存储 UDT 的有效本机表示形式。如果 UDT 为简单形式并且只包含以下类型的字段,则建议采用 Native 格式:
bool、byte、sbyte、short、ushort、int、uint、long、ulong、float、double、SqlByte、SqlInt16、SqlInt32、SqlInt64、SqlDateTime、SqlSingle、SqlDouble、SqlMoney, SqlBoolean
由上述类型的字段构成的值类型十分适合于 Native 格式,例如 C# 中的 structs(或者 Visual Basic 中已知的 Structures)。例如,用 Native 序列化格式指定的 UDT 可以包含也用 Native 格式指定的其他 UDT 的字段。如果 UDT 定义更复杂并且所包含的数据类型不在上述列表中,您必须改为指定 UserDefined 序列化格式。
Native 格式具有以下要求:
-
该类型不得指定 MaxByteSize 的值。
-
所有字段必须都是可序列化的。
-
如果 UDT 是在类中定义的并且不是结构,则必须将 StructLayoutAttribute 指定为 StructLayout.LayoutKindSequential。此属性控制数据字段的实际布局并用于强制成员按它们出现的顺序排列。SQL Server 使用此属性确定具有多个值的 UDT 的字段顺序。
用户自定义序列化,在我们自己编写“用户自定义类型”时,需要使用UserDefined,即需要将系统自动生成的代码
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]修改为:
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined)]
SqlUserDefinedTypeAttribute 属性的 UserDefined 格式设置使开发人员能够完全控制二进制格式。在将 Format 特性属性指定为 UserDefined 时,您需要在代码中采取以下操作:
-
指定可选的 IsByteOrdered 特性属性。默认值为 false。
-
指定 SqlUserDefinedTypeAttribute 的 MaxByteSize 属性。
-
通过实现 IBinarySerialize 接口,编写代码以便为 UDT 实现 Read 和 Write 方法。
好了,上面的内容是我们再进行编写我们自己的“用户自定义类型”前需要了解的,呵呵。我也是了解了这么多,然后就开始试着写自己的“用户自定义类型”。例子比较简单,就是把输入的时间统一成一个时间格式。希望能达到理解“用户自定义类型”的目的。代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 using System.Data;
3 using System.Data.SqlClient;
4 using System.Data.SqlTypes;
5 using Microsoft.SqlServer.Server;
6
7 [Serializable]
8 [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined,MaxByteSize=4000)]
9 public struct TypeTime : INullable,IBinarySerialize
10 {
11 #region//实现IBinarySerizlize的Read和Write方法
12
13 public string result;
14
15 public void Read(System.IO.BinaryReader r)
16 {
17
18 this.result = r.ReadString();
19 }
20
21 public void Write(System.IO.BinaryWriter w)
22 {
23
24 w.Write(this.result);
25 }
26
27 #endregion
28
29 public override string ToString()
30 {
31 // 用您的代码替换下列代码
32 return result;
33 }
34
35 public bool IsNull
36 {
37 get
38 {
39 // 在此处放置代码
40 return m_Null;
41 }
42 }
43
44 public static TypeTime Null
45 {
46 get
47 {
48 TypeTime h = new TypeTime();
49 h.m_Null = true;
50 return h;
51 }
52 }
53
54 public static TypeTime Parse(SqlString s)
55 {
56 if (s.IsNull)
57 return Null;
58 TypeTime u = new TypeTime();
59 // 在此处放置代码
60 u.result = OneTime(s);
61 return u;
62 }
63
64 /// <summary>
65 /// 将输入的时间格式统一
66 /// </summary>
67 /// <param name="str"></param>
68 /// <returns></returns>
69 public static string OneTime(SqlString str)
70 {
71 return Convert.ToDateTime(str.Value).ToShortDateString() + Convert.ToDateTime(str.Value).ToShortTimeString();
72 }
73
74
75 // 私有成员
76 private bool m_Null;
77 }
78
79
80
其中系统自动生成的两个方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 public string Method1()
3 {
4 //在此处插入方法代码
5 return "Hello";
6 }
7
8 // 这是占位符静态方法
9 public static SqlString Method2()
10 {
11 //在此处插入方法代码
12 return new SqlString("Hello");
13 }
Method1和Method2可以删掉,替换成自己的方法。
其中需要注意的问题有这么几个:
1.[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined,MaxByteSize=4000)]
public struct TypeTest : INullable,IBinarySerialize 需要同时实现INullable和IBinarySeralize两个接口;
2.实现IBinarySeralize的Read和Write两个方法;
3.SqlString是数据库类型,使用的时候,需要使用它的.value属性,转换成数据类型string 才能使用。
好了,这个问题被解决掉了。
碰到问题的时候,要冷静,知道自己想要什么,剩下的就是想办法去拿;自己不知道怎么能拿到,呵呵,就看看谁拿到了,然后跟人家学就好了。话是这么说的,我也是这么告诉自己的,呵呵,有时候,我也会因为某个问题没能解决头大。慢慢来,告诉自己冷静就好,问题的产生,就是用来解决的。开心,好运!