带有varbinary(max)OUTPUT的CLR存储过程失败,但过程与T-SQL相同

时间:2011-11-30 21:06:37

标签: c# sql-server-2008 tsql sqlclr

我有一个存储过程:

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。

1 个答案:

答案 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);