SQLCLR(四)用户定义类型UDT
用户自定义类型是SQL Server 2005的新特性。和前几篇文章介绍的SQLCLR相比,UDT相对有此复杂。UDT也有许多限制和必须遵守UDT规范。UDT的二进制不能超过8000个字节,必须包含一个null值表示,因为SQLServer的数据类型是允许null值的。
UDT可以是结构或类。如果是类的话需加[StructLayout(LayoutKind.Sequential)]
标签(属性),这是保证序列化时不改变属性的次序。
现在看一段代码
using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize = 1024)]
public struct Person : INullable, IBinarySerialize
{
public override string ToString()
{
// 用您的代码替换下列代码
return FormatU();
}
public bool IsNull
{
get
{
// 在此处放置代码
return m_Null;
}
}
public static Person Null
{
get
{
Person h = new Person();
h.m_Null = true;
return h;
}
}
public static Person Parse(SqlString s)
{
if (s.IsNull)
return Null;
Person u = new Person();
string value = s.Value;
if (value == "null") return Null;
string[] parts = value.Split(',');
u.name = parts[0];
u.age = ParseAge(parts[1]);
u.sex = parts[2];
return u;
}
// 这是占位符方法
public string FormatU()
{
//在此处插入方法代码
return string.Format("名称:{0},年龄:{1},性别:{2}", name, age, sex);
}
// 这是占位符静态方法
public static int ParseAge(string str)
{
//在此处插入方法代码
return int.Parse(str.Substring(0, str.LastIndexOf("岁")));
}
// 这是占位符字段成员
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string sex;
public string Sex
{
get { return sex; }
set { sex = value; }
}
// 私有成员
private bool m_Null;
public byte[] b;
public void Read(BinaryReader r)
{
name = r.ReadString();
sex = r.ReadString();
age = r.ReadInt32();
m_Null = r.ReadBoolean();
}
public void Write(BinaryWriter w)
{
w.Write(name);
w.Write(sex);
w.Write(age);
w.Write(m_Null);
}
}
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize = 1024)]
public struct Person : INullable, IBinarySerialize
{
public override string ToString()
{
// 用您的代码替换下列代码
return FormatU();
}
public bool IsNull
{
get
{
// 在此处放置代码
return m_Null;
}
}
public static Person Null
{
get
{
Person h = new Person();
h.m_Null = true;
return h;
}
}
public static Person Parse(SqlString s)
{
if (s.IsNull)
return Null;
Person u = new Person();
string value = s.Value;
if (value == "null") return Null;
string[] parts = value.Split(',');
u.name = parts[0];
u.age = ParseAge(parts[1]);
u.sex = parts[2];
return u;
}
// 这是占位符方法
public string FormatU()
{
//在此处插入方法代码
return string.Format("名称:{0},年龄:{1},性别:{2}", name, age, sex);
}
// 这是占位符静态方法
public static int ParseAge(string str)
{
//在此处插入方法代码
return int.Parse(str.Substring(0, str.LastIndexOf("岁")));
}
// 这是占位符字段成员
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string sex;
public string Sex
{
get { return sex; }
set { sex = value; }
}
// 私有成员
private bool m_Null;
public byte[] b;
public void Read(BinaryReader r)
{
name = r.ReadString();
sex = r.ReadString();
age = r.ReadInt32();
m_Null = r.ReadBoolean();
}
public void Write(BinaryWriter w)
{
w.Write(name);
w.Write(sex);
w.Write(age);
w.Write(m_Null);
}
}
部署后在SQL Server 2005中执行下面的语句
create table UdtTest (Id int not null, p Person not null)
insert into UdtTest values(1, 'David,24岁,男')
select id, convert(nvarchar(25),p) from UdtTest
drop table UdtTest
结果如下insert into UdtTest values(1, 'David,24岁,男')
select id, convert(nvarchar(25),p) from UdtTest
drop table UdtTest
想看清楚SQLCLR在对UDT处理机制可以将项目附加到SQL Server 2005进程,在相应的方法设置断点。
附:我在写随笔查阅资料时,无意中发现的用VB.NET讲解SQLCLR的PDF文档,相信对用VB.NET的兄弟会有些帮助/Files/DavidFan/HOL067.rar