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#.
Strange. Try changing the C# code from :
To :
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 :
to :