1,表值函数
所谓表值函数就是说这个函数返回的结果是一个Table,而不是单个的值.
在.NET 中创建这样的函数,返回的结果是一个IEnumerable接口.这个接口非常灵活,所有.NET数组集合等都是实现了该接口的.下面我们举一个简单的例子来说明.
在VS2005中创建一个类Student,这个就是我们要返回的表的内容,类下面有属性int Age,string sName,DateTime Birthday,int SID;
然后在另外一个类UserFunction中写入如下代码:
 [SqlFunction(FillRowMethodName="FillRow")]
[SqlFunction(FillRowMethodName="FillRow")] public static IEnumerable GetStudent()
public static IEnumerable GetStudent()
 ...{
...{ Hashtable hash = new Hashtable();
    Hashtable hash = new Hashtable(); for(int i=0;i<3;i++)
    for(int i=0;i<3;i++)
 ...{
    ...{ Student s = new Student();
     Student s = new Student(); s.SID = i;
     s.SID = i; ...
     ... hash.Add(i, s);
     hash.Add(i, s); }
    } return hash.Values;
    return hash.Values; }
} public static void FillRow(object obj, ref SqlInt32 id, ref SqlString name, ref SqlDateTime bir, ref SqlInt32 age)
public static void FillRow(object obj, ref SqlInt32 id, ref SqlString name, ref SqlDateTime bir, ref SqlInt32 age)
 ...{
...{ Student s = (obj as Student);
    Student s = (obj as Student); id = s.SID;
    id = s.SID; name = s.sName;
    name = s.sName; bir = s.Birthday;
    bir = s.Birthday; age = s.Age;
    age = s.Age; 
     }
}
这样写完成以后,在数据库那边添加好这个程序集,然后就可以创建表值函数了:
 create function BuildTable()
create function BuildTable() returns table(SID int,[sName] nvarchar(100),Birthday datetime,Age int)
returns table(SID int,[sName] nvarchar(100),Birthday datetime,Age int) as
as external name SQLFunction.[SQLFunction.UserFunction].GetStudent
external name SQLFunction.[SQLFunction.UserFunction].GetStudent这儿就不用太多的解释了,就是将名为SQLFunction的程序集中的[名字空间.类].方法添加到BuildTable函数中.
这儿需要说明一下就是数据库中的类型和.NET中的类型的对应问题.int,datetime就不说了,主要是.NET中的string,在数据库中没有string类型,在FillRow中指出了类型SqlString,而这个类型的对应是nchar,nvarchar.这儿不能对应char,varchar,我不知道为什么必须是对应nchar的.所以上面我们写的是[sName] nvarchar(100).
大功告成,测试一下,输入语句select * from BuildTable()看看返回你的表没有.
2.存储过程
CLR存储过程和CLR函数非常相似,不过有几点更高的能力:
CLR存储过程可以有一个返回值,也可以写输出参数,可以返回消息给客户程序,可以调用DDL和DML语句.
.NET创建存储过程要编写为静态函数,然后加上SqlProcedure属性.
比如我们写一个简单的存储过程
 [SqlProcedure]
[SqlProcedure] public static int Add(int a, int b)
public static int Add(int a, int b)
 ...{
...{ return a + b;
    return a + b; }
}然后在数据库中写入:
 create procedure Add2Num
create procedure Add2Num @a int,@b int
@a int,@b int as
as external name SQLFunction.[SQLFunction.UserFunction].[Add]
external name SQLFunction.[SQLFunction.UserFunction].[Add]整个代码我就不用解释了,和前面创建函数一样.
我们运行看看结果:
 declare @a int
declare @a int exec @a=Add2Num 10,12
exec @a=Add2Num 10,12 print @a
print @a3.用户定义类型(UDT)
要创建UDT类必须符合"UDT规范",.NET中的约束如下:
他们必须带SqlUserDefinedType 属性
必须带有Serializable属性
必须实现INullable接口
必须博阿訇公开和静态的Parse和ToString方法以用于转换数据类型字符串或逆向转换.
必须暴露数据元素为公开字段或公开属性.
好,那我们就创建一个简单的UDT复数类如下:
 [Serializable]
 [Serializable] [SqlUserDefinedType(Format.Native)]
    [SqlUserDefinedType(Format.Native)] [StructLayout(LayoutKind.Sequential)]
    [StructLayout(LayoutKind.Sequential)] public class Complex:INullable
   public class Complex:INullable
 ...{
    ...{ bool isNull=false;
       bool isNull=false; double real, imag;
       double real, imag; public bool IsNull
       public bool IsNull
 ...{
       ...{
 get ...{ return isNull; }
           get ...{ return isNull; } }
       } public double Real
       public double Real
 ...{
       ...{
 get ...{ return real; }
           get ...{ return real; }
 set ...{ real = value; }
           set ...{ real = value; } }
       } public double Imag
       public double Imag
 ...{
       ...{
 get ...{ return imag; }
           get ...{ return imag; }
 set ...{ imag = value; }
           set ...{ imag = value; } }
       } public override string ToString()
       public override string ToString()
 ...{
       ...{ if (isNull)
           if (isNull)
 ...{
           ...{ return "NULL";
               return "NULL"; }
           } else
           else
 ...{
           ...{ return real + "," + imag;
               return real + "," + imag; }
           } }
       } public static Complex Parse(SqlString s)
        public static Complex Parse(SqlString s)
 ...{
        ...{ if (s == null || s.IsNull)
            if (s == null || s.IsNull)
 ...{
            ...{ return null;
                return null; }
            } else
            else
 ...{
            ...{ Complex c = new Complex();
                Complex c = new Complex(); string str = Convert.ToString(s);
                string str = Convert.ToString(s); string[] st = str.Split(',');
                string[] st = str.Split(','); c.real = Convert.ToDouble(st[0]);
                c.real = Convert.ToDouble(st[0]); c.imag = Convert.ToDouble(st[1]);
                c.imag = Convert.ToDouble(st[1]); return c;
                return c; }
            } }
        } }
    } create type Complex
create type Complex external name SQLFunction.[SQLFunction.Complex]
external name SQLFunction.[SQLFunction.Complex]这样我们就创建好了用户定义类型Complex.
数据库事例代码中有相关内容,参见:
\Program Files\Microsoft SQL Server\90\Samples\Engine\Programmability\CLR\UserDefinedDataType
 
 
                     
            
        













 
                    

 
                 
                    