我有一个存储过程:
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。
答案 0 :(得分:2)
奇怪。尝试更改C#代码:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void BackupStuff(string dataID, out byte [] backup)
{
[..body omitted..]
}
致:
using System.Data.SqlTypes;
...
[Microsoft.SqlServer.Server.SqlProcedure]
public static void BackupStuff(string dataID, out SqlBinary backup)
{
[..body omitted..]
byte[] result = ... // get byte array to return
backup = new SqlBinary(result);
}
使用SqlBinary作为C#例程的返回类型对我有用。
编辑: 好吧,使用SqlBinary或byte []都适合我。 你的varbinary(max)参数叫做“@backup”或“@backupdata”吗?看起来您展示的示例代码使用两者。 即尝试改变:
SqlParameter p = new SqlParameter("@backupdata",
SqlDbType.VarBinary, -1);
到:
SqlParameter p = new SqlParameter("@backup",
SqlDbType.VarBinary, -1);