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


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

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

         
    CREATE TYPE SSN
    FROM varchar(11NOT 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'

         是不是很简单?呵呵

  • 相关阅读:
    MySQL安装图解
    程序员感触
    一个人的生活
    开始懂了
    limit 检索记录行
    Ajax的完整兼容各种浏览器版本代码
    java.lang.UnsupportedClassVersionError: Unsupported major.minor version 49.0的错误 [转]
    通信协议
    SDK
    毕业三个多月的感悟
  • 原文地址:https://www.cnblogs.com/sdlfx/p/1511296.html
Copyright © 2020-2023  润新知