在 Type 的属性设置中,因为记录 Type 设置的 m_Type 私有变量是数值类型,但显示结果与用户设置数据时,需要的是文本类型。因此在取得 Type 属性值的 Get 函数中,我们利用 Select Case 语法将 m_type 的值转成文本返回。同理在设置属性的 Set 函数中,对应设置的文本转成不同的数值放入到 m_type 变量中。
你可以通过如下的 T-SQL 语法测试设置的 Type 类型是否合乎规范,是否我们所建立的实例会存放在对应的设置中,也就是“类型不明”:
--使用错误的数据类型进行测试
SELECT CONVERT(Seat,N'0,赛车').Type,CONVERT(Seat,N'0,赛车').Size
SELECT CONVERT(Seat,'').Type
SELECT CONVERT(Seat,NULL).Type
上述分别测试出输入的 Type 不符要求,以及先前编写的类处理空字符串与 NULL 转换成 Seat 类型实例的逻辑,其结果都约略如图11-23所示:
图11-23 测试数据错误的结果
接下来我们测试把对象存入到含有上述自定义类型的数据表中,首先通过 T-SQL 创建测试用的数据表BikeSeats,语法如下:
CREATE TABLE BikeSeats
(
SeatID INT IDENTITY NOT NULL,
SeatInfo Seat ,
)
利用 T-SQL 添加一条数据到 BikeSeats 数据库中:
DECLARE @s Seat
SET @s.Size=25
SET @s.Type=N'香蕉椅' --可以把此栏故意设错,观察 Exception
INSERT BikeSeats VALUES(@s)
在上述范例中声明 Seat 类型的变量,赋予各项属性后再插入到数据表中。接着用下列语法将记录从 BikeSeats 数据表中调出来,并将 Seat 对象实例转型成文字:
SELECT CONVERT(NVARCHAR,SeatInfo) FROM BikeSeats
你将会得到如图11-24 的结果,这也验证了先前 ToString 函数的程序逻辑:
图11-24 新建与查询数据表内含有自定义数据类型字段的结果
介绍完编写UDT类基本的要求后,我们再在类中增加一些功能。以下用 Desk 类做进一步的说明J
11.3.4.3 用户自定义数据类型较高级的范例
程序代码列表11-16另外创建 Desk 类,由于 SqlUserDefinedType 属性的 Format 参数使用的是 UserDefined,因此需要设置数据类型实例最大的字节数 MaxByteSize,由于等会要对数据字段进行排序,所以IsByteOrdered 必须设置 True,在后文中也会利用此项设置来比较对象实例的大小。
接下来,我们针对 Desk 类再进一步地提供自定义序列化的能力,并为该类加上自定义函数 GetPrice。
程序代码列表11-16 实现 IComparable 接口的 Write 和 Read 函数
'User Defined Type 一定需要能够 Searialize 才能整个地放到数据表字段中
<Serializable(), SqlUserDefinedType(Format.UserDefined, _
MaxByteSize:=4000, IsByteOrdered:=True), _
Runtime.InteropServices.StructLayout(LayoutKind.Sequential)> _
Public Class Desk
Implements INullable, IBinarySerialize, IComparable
Private is_Null As Boolean = True
Private m_size As Short
'因为是自定义 Serialize 所以可以序列化文本类型的成员
Private m_type As String
Public Sub New()
m_size = -1
m_type = "类型不明"
is_Null = True
End Sub
Public Sub Write(ByVal w As System.IO.BinaryWriter) _
Implements IBinarySerialize.Write
Dim bNull As Byte
If is_Null Then
bNull = 0
w.Write(bNull)
Else
bNull = 1
w.Write(bNull)
w.Write(m_size)
w.Write(m_type)
End If
End Sub
Public Sub Read(ByVal r As System.IO.BinaryReader) _
Implements IBinarySerialize.Read
Dim bNull As Byte = r.ReadByte()
If bNull = 0 Then
is_Null = True
Else
is_Null = False
m_size = r.ReadInt16
m_type = r.ReadString()
End If
End Sub
由于我们自定义序列化实例的方式,所以在实现写入到媒介(如硬盘,网络等)的 Write 方法时,要将各属性依次写入,并要将该实例是否为 NULL 的条件一并写入。而实现 Read 方法读出先前存储的状态,做反序列化的操作。也就是提供相同顺序读取不同数据类型的数据,并赋予到当前的实例变量中。
我们还替 Desk 类实现了 IComparable 接口,该界面只有一个函数定义,就是 CompareTo 函数。该函数要求对象实例自身在与传入的对象实例比大小时,我们所实现的商业逻辑必须要返回大于零的值代表当前的实例比较大,若两个实例相等则返回零,若参数传入的实例比较大,则返回负值。程序代码范例如列表11-17:
程序代码列表11-17 实现 IComparable 接口的 CompareTo 函数
Public Function CompareTo(ByVal obj As Object) As Integer _
Implements IComparable.CompareTo
'我们以两个对象的字符串结果来比较大小
'如果当前的 Instance 是和 Nothing 对象来比,当然比较大
If obj Is Nothing Then Return 1
Dim desk As Desk = CType(obj, Desk)
If (Me.IsNull) Then
If desk.IsNull Then Return 0
Return -1
Else
If desk.IsNull Then Return 1
Return Me.ToString.CompareTo(desk.ToString())
End If
End Function
在上述的范例中,仅以该对象的字符串表示来比较大小。另外,我们将编写一个用户自定义函数来调用 CompareTo方法如程序代码列表11-18所示。
我们最后在 Desk 类中加上一个自定义的方法,以此测试通过自定义数据类型是否也可以调用该类的方法,在下文中会通过 T-SQL 来调用这个方法:
程序代码列表11-18 为自定义数据类型新建函数
Public Function GetPrice() As Integer
Dim intMoney As Integer
Select Case m_type
Case类型不明"
intMoney = -1
Case "小圆桌"
intMoney = 100
Case "餐桌"
intMoney = 200
Case "小方桌"
intMoney = 300
End Select
Return intMoney
End Functio程序
由于 Type 属性现在是用字符串类型的 m_type变量在记录设置值,因此,不需要通过 Select Case 语法做转换对应字符串与数值的操作,程序代码较为简单,如列表11-19所示:
程序代码列表11-19 Desk类型的Size和ype属性
Public Property Size() As Short
Get
Return Me.m_size
End Get
Set(ByVal Value As Short)
m_size = Value
Me.is_Null = False
End Set
End Property
Public Property Type() As String
'强制用户输入的 Type 只能是小圆桌,餐桌,小方桌
Get
Return m_type
End Get
Set(ByVal Value As String)
If Value <> "小圆桌" And Value <> "餐桌" And Value <> "小方桌" And Value <> "类型不明" Then
Throw New ArgumentException("Type 类型必须填入小圆桌,餐桌,小方桌三者之一")
Else
m_type = Value
Me.is_Null = False
End If
End Set
End Property
另外,ToString 和 Parse 函数与前述的 Seat 类差异不大,在此也就不再详列。整个类编译并部署完毕后,通过 T-SQL 语法创建包含该类的数据表字段定义如下:
--将先前测试的 BikeSeats 数据库删除,重建一个自定义类型的数据表
DROP TABLE BikeSeats
CREATE TABLE BikeSeats
(
SeatID INT IDENTITY NOT NULL,
--利用用户自定义数据类型定义字段
SeatInfo Seat ,
DeskInfo Desk
)
上一页 [1] [2] [3] [4] [5] [6] 下一页
责任编辑:cyth