之前对这个“用户自定义类型”只是有所耳闻,没有机会用过,也没有自己动手去写过。今天朋友让我写一个简单的“用户自定义类型”,呵呵,糗了。

下面是目前对它的了解。

  在VS2008中新建项目选择“数据库”—“SQL Server项目”,上面的combobox选择".NET Framework2.0"

输入项目名称,选择好自己的项目所在文件夹,点解确认后,会提示:

选择要使用“用户自定义类型”的数据库,在“添加新引用”中找到目标数据库,点击“确定”即可。

进入项目后,在解决方案上“右键”—“添加”—“用户定义的类型”。如图所示

在这里面可以添加“用户定义的函数”、“存储过程”、“聚合”、“触发器”等。选择“用户定义的类型”,后便可看到可以编辑的代码层。

  下面,在进行编码前,我们来了解一些内容,呵呵,这些内容,也是我边做边查的。呵呵,很庆幸,碰到不会的东西,能查一查,问一问,呵呵,也是件很好的事情。

  1.实现“用户定义的类型”UDT的要求:

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

这个对应的就是上面的代码 public struct TypeTest:INullable。需要实现Null性,对null性的处理,是在这里处理的。

1   public static TypeTest 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 为空值后,可以使用其本机空值处理方法。

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

该方法的处理,是在这段代码中进行处理的:

1   public override string ToString()
2     {
3         // 用您的代码替换下列代码
4         return "";
5     }

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

对Read和Write方法的实现是在实现接口IBinarySerialize时需要处理的。处理方法如下:

代码

 1 
 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 必须实现 System.Xml.Serialization.IXmlSerializable,或者所有公共字段和属性必须均属于 XML 可序列化类型或者使用 XmlIgnore 属性进行修饰(如果要求替代标准序列化)。
一个 UDT 对象必须只存在一个序列化。如果序列化或反序列化例程识别了某一特定对象的多个表示形式,则验证将失败。
为了确保服务器将字节顺序的比较用于 UDT 值,SqlUserDefinedTypeAttribute.IsByteOrdered 必须为 true
在类中定义的 UDT 必须具有不采用任何参数的公共构造函数。您可以选择创建其他重载类构造函数。
该 UDT 必须将数据元素作为公共字段或属性过程公开。
公共名称不能长于 128 个字符,并且必须符合在标识符中定义的针对标识符的 SQL Server 命名规则。
sql_variant 列不能包含 UDT 的实例。
继承的成员无法从 Transact-SQL 访问,因为 SQL Server 类型系统不知道 UDT 中的继承层次结构。但是,您可以在创建类的结构时使用继承,并且可以在该类型的托管代码实现方式中调用此类方法。
成员不能被重载,但类构造函数除外。如果您创建某一重载方法,则在 SQL Server 中注册程序集或创建类型时将不会引发错误。在运行时将检测到重载的方法,而不是在创建类型时检测到。只要永不调用重载的方法,重载的方法就可以存在于类中。一旦您调用重载的方法,就会引发错误。
任何 static(或 Shared)成员都必须声明为常量或声明为只读。静态成员将无法改变。
从 SQL Server 2008 开始,如果 SqlUserDefinedTypeAttribute.MaxByteSize 字段设置为 -1,则序列化 UDT 在大小上可达到大对象 (LOB) 大小限制(目前为 2 GB)。该 UDT 的大小不能超过在 MaxByteSized 字段中指定的值。

编写用户类型的本地序列化:

  为 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 方法。

好了,上面的内容是我们再进行编写我们自己的“用户自定义类型”前需要了解的,呵呵。我也是了解了这么多,然后就开始试着写自己的“用户自定义类型”。例子比较简单,就是把输入的时间统一成一个时间格式。希望能达到理解“用户自定义类型”的目的。代码如下:

代码

 1 using System;
 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 

其中系统自动生成的两个方法

代码

 1   // 这是占位符方法
 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 才能使用。

好了,这个问题被解决掉了。

碰到问题的时候,要冷静,知道自己想要什么,剩下的就是想办法去拿;自己不知道怎么能拿到,呵呵,就看看谁拿到了,然后跟人家学就好了。话是这么说的,我也是这么告诉自己的,呵呵,有时候,我也会因为某个问题没能解决头大。慢慢来,告诉自己冷静就好,问题的产生,就是用来解决的。开心,好运!

转载于:https://www.cnblogs.com/angleSJW/archive/2010/04/20/1716282.html

SQL2005 用户自定义类型相关推荐

  1. 用户自定义类型(User-defined Type)参数的传递

    用户自定义类型(User-defined   Type)参数的传递         用户自定义类型在VB中是一种重要的数据类型,它为编程者提供了很大的灵活性,使开发人员可以根据需要构造自己的数据结构. ...

  2. 使用用户自定义类型作为map的key

    有时候我们想把用户自定义类型作为std::map的键值. 方法一)最简单的方法就是实现该自定义类型的<操作符,代码如下: class Foo { public:     Foo(int num_ ...

  3. 【Spring 工厂】注入详解 — Set注入(JDK内置类型,用户自定义类型)、构造注入(重载)

    Spring 注入(Injection) 什么是注入? 为什么要注入? 如何进行注入[开发步骤] Spring注入的原理分析(简易版) Set注入详解 JDK内置类型 String+8种基本类型 数组 ...

  4. c语言用户自定义类型,c语言用户自定义数据类型.ppt

    c语言用户自定义数据类型 第十一章 涛锗悯举诌痕枣升萤囊鹏沙晰幂龟杖尿留梗散干巫侯昆秦船峨扬焰杂裤堪c语言用户自定义数据类型c语言用户自定义数据类型 本章要点 结构体的概念 结构体的定义和引用 结构体 ...

  5. Lua入门(三)用户自定义类型userdata

    userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct .指针和类)存储到 Lua 变量中 ...

  6. 【Android】使用AIDL传递用户自定义类型数据--附完整示例代码

    AIDL对Java类型的支持 AIDL支持Java原始数据类型 AIDL支持String和CharSequence AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语 ...

  7. Python 中的用户自定义类型

    Python中面向对象的技术 Python是面向对象的编程语言,自然提供了面向对象的编程方法.但要给面向对象的编程方法下一个定义,是很困难的.问题关键是理解对象 的含义.对象的含义是广泛的,它是对现实 ...

  8. Spring用户自定义类型

    第一种方式 [开发步骤]: 为成员变量提供 set get 方法 配置文件中进行注入(赋值) <bean id="userService" class="com.l ...

  9. Go 学习笔记(33)— Go 自定义类型 type(自定义结构体、结构体初始化、结构体内嵌、自定义接口)

    1. 自定义类型格式 用户自定义类型使用关键字 type ,其语法格式是: type newType oldType oldType 可以是自定义类型.预声明类型.未命名类型中的任意一种. newTy ...

最新文章

  1. mysql修改网络服务_MySql-Server 就要修改成允许 Web-Server 进行远程连接. 最后一步 需要使用ALTER USER … ACCOUNT UNLOCK语句进行解锁了:...
  2. MRI炎症和结构损伤指标对TNF拮抗剂治疗AS患者获持续缓解的预测价值
  3. Resource interpreted as Script but transferred with MIME type text/plain:
  4. Effective Java之使类和成员的可访问性最小化(十三)
  5. mysql期末考试选择题
  6. sonar.exclusions 配置无效问题
  7. 一些图形学中的数学应用
  8. typedef的四个用途和两个陷阱
  9. Spring中的事务回滚 网上比较不错的文章
  10. 学术论文写作的 paper、code 资源
  11. 由Java编写的在线教育系统源码有何优势?
  12. 七星彩长奖表图_够力七星彩奖表长条图app
  13. 手把手教你破解无线路由器密码
  14. 流年似水 启航2019
  15. 一个老码农对职场的思考
  16. UE4 渲染半透明物体进深度剔除(复制物体)
  17. 【odoo15】由于目标计算机积极拒绝,无法连接。
  18. Java编程思想+Effective Java+Java核心技术+Java核心技术 卷II+Java语言程序设计(中文+英文+源码)
  19. python爬虫解析数据包_Python网络爬虫之三种数据解析方式
  20. 基于SpringBoot+jpa+Erupt的出入登记签到打卡系统

热门文章

  1. Hi3516A开发--烧写/启动模式
  2. java获取注解信息_java 自定义注解,获取注解信息
  3. linux下调试thread 类_在 RISC-V 芯片 GD32V 上运行 RT-Thread
  4. LBE平行空间的技术实现
  5. TFboys:使用Tensorflow搭建深层网络分类器
  6. 【David Silver强化学习公开课之一】强化学习入门
  7. 【问链财经-区块链基础知识系列】 第三十二课 从区块链溯源来看农产品链的设计
  8. Hdu 1269.迷宫城堡
  9. android表情输入键盘,GitHub - UKfire/Emotion: 帮你的Android应用快速集成表情键盘
  10. 数学之美 系列八-- 贾里尼克的故事和现代语言处理