C#编写扩展存储过程

C#编写扩展存储过程,实际上是利用C#写个dll,注册之后在sql中调用而已。理论性的东西本人过于薄弱,讲不出什么道道,还是先来看一个简单的示例吧:

1、首先,建一个类库项目,新建类文件CsharpHelper.cs.包含代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
None.gifusing System; 
None.gif
using System.Runtime.InteropServices; 
None.gif
using System.Reflection; 
None.gif
using System.Runtime.CompilerServices; 
None.gif
None.gif[assembly: AssemblyTitle(
"SQLInterop")] 
None.gif[assembly: AssemblyDescription(
"Test SQL .NET interop")] 
None.gif[assembly: AssemblyVersion(
"1.0.0.1")] 
None.gif[assembly: AssemblyDelaySign(
false)] 
None.gif
namespace SQLInterop
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public interface ICsharpHelper
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
string Hello();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    [ClassInterface(ClassInterfaceType.AutoDispatch)]
InBlock.gif    
public class CsharpHelper : ICsharpHelper
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public string Hello()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return "Hello from CSharp";
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 
注意记得把自动生成的那个类库信息文件删掉。

2、使用VS里的命令提示,生成强命名文件:sn -k HelperKey.snk
3、编译这个类文件,记得把snk加上去:csc /t:library /keyfile:HelperKey.snk CsharpHelper.cs
4、注册dll:regasm /tlb:CsharpHelper.tlb CsharpHelper.dll /codebase
 

至此dll的准备工作完成了,下面在sql里试试看,打开查询分析器(用sa或具有相应权限的账户登录),选中master数据库,书写sql语句如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
declare @object int
declare @hr int
declare @property varchar(255)
declare @return varchar(255)
declare @src varchar(255), @desc varchar(255)

-- 创建对象实例。 
exec @hr = sp_OACreate 'SQLInterop.CsharpHelper'@object out
if @hr <> 0
begin
    
exec sp_OAGetErrorInfo @object@src out, @desc out
    
select hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
    
return
end

-- 调用对象方法。 
exec @hr = sp_OAMethod @object'Hello'@return out
if @hr <> 0
begin
    
exec sp_OAGetErrorInfo @object@src out, @desc out
    
select hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
    
return
end
print @return

-- 销毁对象实例。
exec @hr = sp_OADestroy @object
if @hr <> 0
begin
    
exec sp_OAGetErrorInfo @object@src out, @desc out
    
select hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
    
return
end

 
看看,是不是输出了"Hello from Csharp"呢?

可能遇到的错误:

a、提示“阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问”,此时可用"exec sp_configure 'Ole Automation Procedures', 1 reconfigure"语句来开启权限,或是在SQLServer功能的外围应用配置器中选中“Ole自动化”。

b、返回0x80131700号错误信息。这个我也没解决。目前只发现在装有sql2000的机器上没碰到此问题。

c、其它错误,请参照sqlserver联机丛书。

或许你会说,仅仅返回一个字符串,有啥用啊?返回个数据集给我看看?没问题,let's go!

 1、再新建一个文件,名为DataHelper.cs,代码如下:

ContractedBlock.gif ExpandedBlockStart.gif DataHelper Code
namespace HisHelper
{
    
public interface IDataHelper
    {
        DataTable GetData(
string name);
    }

    [ClassInterface(ClassInterfaceType.AutoDual)]
    
public class DataHelper : IDataHelper
    {
        
private static string _connstr = "Password={0};Persist Security Info=True;User ID={1};Initial Catalog={2};Data Source={3};Connect Timeout=10;";
        
private static string _testsql = "select * from [user] where [name] like '%@name%'";

        
private SqlConnection CreateConnection(string server, string logid, string logpass)
        {
            
return new SqlConnection(string.Format(_connstr, logpass, logid, "his_nh", server));
        }

        
public DataTable GetData(string name)
        {
            SqlParameter parm 
= new SqlParameter("@name", SqlDbType.VarChar, 12);
            parm.Value 
= name;
            DataTable dt 
= SqlHelper.ExecuteDataset(CreateConnection(".""sa"string.Empty), CommandType.Text, _testsql, parm).Tables[0];
            
return dt;
        }
    }
}

ExpandedBlockStart.gif
None.gifnamespace HisHelper
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public interface IDataHelper
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        DataTable GetData(
string name);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    [ClassInterface(ClassInterfaceType.AutoDual)]
InBlock.gif    
public class DataHelper : IDataHelper
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private static string _connstr = "Password={0};Persist Security Info=True;User ID={1};Initial Catalog={2};Data Source={3};Connect Timeout=10;";
InBlock.gif        
private static string _testsql = "select * from [user] where [name] like '%@name%'";
InBlock.gif
InBlock.gif        
private SqlConnection CreateConnection(string server, string logid, string logpass)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return new SqlConnection(string.Format(_connstr, logpass, logid, "his_nh", server));
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public DataTable GetData(string name)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            SqlParameter parm 
= new SqlParameter("@name", SqlDbType.VarChar, 12);
InBlock.gif            parm.Value 
= name;
InBlock.gif            DataTable dt 
= SqlHelper.ExecuteDataset(CreateConnection(".""sa"string.Empty), CommandType.Text, _testsql, parm).Tables[0];
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 2、再按照之前说的那几个步骤,生成snk文件,编译,注册。在查询分析器里调用:

ContractedBlock.gif ExpandedBlockStart.gif DataHelper Sql Code
exec @hr = sp_OACreate 'HisHelper.DataHelper'@object out
exec @hr = sp_OAMethod @object'GetData'@return out, '张三'
--省略了部分代码

 执行之后发现什么?oh my god,是不是出错了?提示“该环境不支持。。。”?没关系,仔细想想,GetData方法返回的是datatable,sql里认不认得这个东西啊?对了,问题就出在这,把datatable转成字符串数组吧!再添加一个方法:

ContractedBlock.gif ExpandedBlockStart.gif Format1 Code
private string[,] FormatDataTable(DataTable dt)
{
    
if (dt == null || dt.Rows.Count == 0)
        
return null;

    string
[,] dataArr = new string[dt.Rows.Count, dt.Columns.Count];

    
for (int i = 0; i < dt.Rows.Count; i++)
    {
        
for (int j = 0; j < dt.Columns.Count; j++)
        {
            dataArr
[i, j] = dt.Rows[i][j].ToString();
        }
    }
    
return dataArr;
}

把GetData里的return语句修改一下:return FormatDataTable(dt); 重新生成并注册,在sql里调用下看看。是不是成功了?可是。。。好像还有点不对,怎么行列似乎被对调了啊?哈哈,再修改下FormatDataTable方法:

ContractedBlock.gif ExpandedBlockStart.gif Format2 Code
private string[,] FormatDataTable(DataTable dt)
{
    
if (dt == null || dt.Rows.Count == 0)
        
return null;

    
string[,] dataArr = new string[dt.Columns.Count, dt.Rows.Count];

    
for (int i = 0; i < dt.Columns.Count; i++)
    {
        
for (int j = 0; j < dt.Rows.Count; j++)
        {
            dataArr[i, j] 
= dt.Rows[j][i].ToString();
        }
    }
    
return dataArr;
}

 再编译,注册,调用,这回没问题了。Over

转载于:https://www.cnblogs.com/sdlfx/archive/2008/09/18/1293482.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值