CLR stored procedure with varbinary(max) OUTPUT fails, but same procedure works as T-SQL

I have a stored procedure:

CREATE PROCEDURE [dbo].[brbackup]
    @dataID [nvarchar](max),
@backupdata [varbinary](max) OUTPUT
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLBackupRestore].[StoredProcedures].[BackupStuff]
GO

Which maps back to this CLR Stored procedure code:

public class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void BackupStuff(string dataID, out byte [] backupdata)
    {
       [..body omitted..]
    }
 }

This works just fine, I can call it in t-sql on the server just fine like this:

declare @backupdata varbinary(max);
exec brbackup "dataIDNumber", @backupdata output;

I get the expected output (several megabytes of data in @backupdata). What I'd like to do is call this from C# through a client, but this doesn't work:

    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();
    }

This query doesn't give an error, and it runs for a while (as expected), but p.Value has nothing in it but a byte[0]. I've tried variations of setting the length to something other than -1, and setting p.Value to a byte[] large enough to hold the results, but no joy.

However, strangely enough creating a small t-sql stored procedure to wrap around the CLR stored procedure DOES work:

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

And then calling the wrapper AA_JUST_TESTING with this C# code:

        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();

Works just peachy. p.Value winds up with a byte [] of just the right size filled with the correct data.

So... I don't see the difference other than one calls a CLR stored procedure and the other calls a T-SQL stored procedure, even though they're both using a varbinary(max) output to return the value. I'm looking for:

  • A plausible explanation, pointer to documentation, etc... that tells me why this works like it does.

  • Some kind of work-around so I don't have to have the wrapper stored procedure, and can maybe just accomplish what I need calling the CLR SP directly from C#.

Answers


Strange. Try changing the C# code from :

[Microsoft.SqlServer.Server.SqlProcedure]
public static void BackupStuff(string dataID, out byte [] backup)
{
   [..body omitted..]
}

To :

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);
    }

Using SqlBinary as the return type of the C# routine works for me.

EDIT : Well, using either SqlBinary or byte[] both work for me. Is your varbinary(max) parameter called "@backup" or "@backupdata" ? Looks like the sample code you show uses both. i.e. try changing :

  SqlParameter p = new SqlParameter("@backupdata", 
                                           SqlDbType.VarBinary, -1);

to :

  SqlParameter p = new SqlParameter("@backup", 
                                           SqlDbType.VarBinary, -1);

Need Your Help

Android: convertView parameter in getView() is not null when it should be null

android listview android-listview

I have a ListView with a custom ArrayAdapter, and according to documentation and what I read everywhere, getView() gets called when creating new view (In this case list item) or recycling an old view

XML based website - how to create?

javascript xml asp-classic

I would like to create an xml based website. I want to use xml files as datasources since it is a kind of online directory site. Can someone please give me a starting point? Are there any good online

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.