【发布时间】:2011-12-01 22:36:11
【问题描述】:
我有一个存储过程:
CREATE PROCEDURE [dbo].[brbackup]
@dataID [nvarchar](max),
@backupdata [varbinary](max) OUTPUT
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLBackupRestore].[StoredProcedures].[BackupStuff]
GO
映射回此 CLR 存储过程代码:
public class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void BackupStuff(string dataID, out byte [] backupdata)
{
[..body omitted..]
}
}
这很好用,我可以像这样在服务器上的 t-sql 中调用它:
declare @backupdata varbinary(max);
exec brbackup "dataIDNumber", @backupdata output;
我得到了预期的输出(@backupdata 中有几兆字节的数据)。我想做的是通过客户端从 C# 调用它,但这不起作用:
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection("myConnString");
conn.Open();
SqlCommand cmd = new SqlCommand("brbackup", conn);
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@dataID", "dataIDNumber");
SqlParameter p = new SqlParameter("@backupdata",
SqlDbType.VarBinary, -1);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
}
这个查询没有给出错误,它运行了一段时间(如预期的那样),但p.Value 除了byte[0] 之外什么都没有。我尝试将长度设置为 -1 以外的值,并将 p.Value 设置为 byte[] 大到足以容纳结果,但没有任何乐趣。
然而,奇怪的是,创建一个小的 t-sql 存储过程来包裹 CLR 存储过程确实有效:
CREATE PROCEDURE AA_JUST_TESTING
@stuff varbinary(max) output
AS
BEGIN
declare @backupdata varbinary(max);
exec brbackup 'dataIDNumber', @backupdata output;
set @stuff = @backup;
END
GO
然后使用此 C# 代码调用包装器 AA_JUST_TESTING:
SqlConnection conn = new SqlConnection("myConnString");
conn.Open();
SqlCommand cmd = new SqlCommand("AA_JUST_TESTING", conn);
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter("@stuff",
SqlDbType.VarBinary, -1);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
效果很好。 p.Value 最终得到一个大小恰到好处的 byte [],其中填充了正确的数据。
所以...除了一个调用 CLR 存储过程而另一个调用 T-SQL 存储过程之外,我看不出有什么区别,即使它们都使用varbinary(max) output 来返回值。我正在寻找:
一个似是而非的解释、指向文档的指针等...告诉我为什么会这样。
某种变通方法,这样我就不必拥有包装存储过程,并且可以直接从 C# 中完成我需要调用 CLR SP 的工作。
【问题讨论】:
标签: c# sql-server-2008 tsql sqlclr