结合C#在MSSQL中定义和使用自定义类型

      之所以会去了解这个,是因为在最近的一个项目中需要用BizTalk来处理业务数据,而每一笔业务数据又对应着表中的很多条记录,发现做BizTalk的同事在实现中,每条记录都要调用一次存储过程,而且主表数据在每一次调用时都要传入,感觉有点不太好。于是想着是不是能用table类型作为存储过程的参数。研究了一下,似乎不行。但是可以用自定义的数据类型。

      定义最普通的自定义类型很简单,见MSDN示例:     

     
CREATE  TYPE SSN
FROM   varchar ( 11 NOT   NULL  ;

 

     

      详细的到帮助文档上看吧。这里主要说一下怎么把用C#定义的类引入到SQL中作为自定的数据类型。

      首先,在VS中定义一个类,这个类必须满足以下几点:

      1、添加Serializable特性以标记为是可序列化的;

      2、添加SqlUserDefinedType特性,注意设置该特性的一些属性值,如Format, Name, MaxByteSize,注意若Format设置为UserDefined的话一定要指定MaxByteSize值;

      3、实现IBinarySerialize接口,该接口中声明了Read和Write两个方法,分别是用于从BinaryReader对象中读取数据到类中的属性和把类中的属性写入到BinaryReader对象;

      4、实现INullable接口,该接口中声明了IsNull的get访问器,用于在sql中判断该类型的变量是否为null;

      5、实现静态的返回类型为当前类类型的Null只读属性,返回一个在sql中认为为null的实例;

      6、实现静态的Parse方法。该方法只有一个SqlString类型参数;

      7、重载基类的ToString方法;

      暂且只知道这一些,来看看我测试用的C#类吧:     

  

using  System;
using  System.Data;
using  System.Data.SqlClient;
using  System.Data.SqlTypes;
using  Microsoft.SqlServer.Server;

namespace  LfxSqlType
{
    [Serializable]
    [SqlUserDefinedType(Format.UserDefined, Name
= " Person " , MaxByteSize = 100 )]
    
public   class  Person : IBinarySerialize, INullable
    {
        
public   string  Name;
        
public   int  Age;
        
public   char  Sex;

        
#region  IBinarySerialize 成员

        
public   void  Read(System.IO.BinaryReader r)
        {
            
string  s  =  r.ReadString();
            
string [] values  =  s.Split( ' | ' );
            Name 
=  values[ 0 ];
            Age 
=  Convert.ToInt32(values[ 1 ]);
            Sex 
=  Convert.ToChar(values[ 2 ]);
        }

        
public   void  Write(System.IO.BinaryWriter w)
        {
            w.Write(
string .Format( " {0}|{1}|{2} " , Name, Age.ToString(), Sex));
        }

        
#endregion

        
#region  INullable 成员

        
public   bool  IsNull
        {
            
get  {  return   string .IsNullOrEmpty(Name); }
        }

        
#endregion

        
public   static  Person Null
        {
            
get {
                Person p 
=   new  Person();
                p.Name 
=   string .Empty;
                
return  p;
            }
        }

        
public   static  Person Parse(SqlString str)
        {
            Person p 
=   new  Person();
            
string [] values  =  str.Value.Split( ' | ' );
            p.Name 
=  values[ 0 ];
            p.Age 
=  Convert.ToInt32(values[ 1 ]);
            p.Sex 
=  Convert.ToChar(values[ 2 ]);
            
return  p;
        }

        
public   override   string  ToString()
        {
            
if  ( this .IsNull)
                
return   " NULL " ;
            
else
                
return   string .Format( " {0}|{1}|{2} " , Name, Age.ToString(), Sex);
        }
    }
}

      再来看看SQL中如何根据这个类来创建自定义类型。首先,得引用该类所在的程序集:      

create  assembly lfxtype
from   ' E:\NetSample\WinForm\SqlCustomerType\LfxSqlType\bin\Debug\LfxSqlType.dll '

      语法是create assembly sql中的程序集名 from 程序集路径。具体参见MSDN。下一步,创建具体的类型:  

create  type person
external name lfxtype.
[ LfxSqlType.Person ]

      语法跟上边的也很类似了。create type 类型名 external name sql中程序集名.[C#类完全限定名]

      接下来就可以做调用测试了:

-- 创建以自定义类型为参数的存储过程
create   proc  test
    
@p  person
as
    
print   @p .Name
go
-- 定义变量
declare   @p  person
-- 赋值
set   @p   =   convert (person ,N ' lfx|2|y ' )
-- 执行存储过程
exec  test  @p
-- 弄个应该为null的值
set   @p   =   convert (person,  ' |2|y ' )
-- 判断是不是真为null
if   @p   is   null
    
print   ' null '

     是不是很简单?呵呵

你可能感兴趣的:(MSSQL)