Хранимая процедура CLR с varbinary (max) OUTPUT завершается неудачно, но такая же процедура работает как T-SQL - PullRequest
3 голосов
/ 01 декабря 2011

У меня есть хранимая процедура:

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

А затем вызывать оболочку AA_JUST_TESTING с этим кодом C #:

        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 для возврата значения. Я ищу:

  • Правдоподобное объяснение, указатель на документацию и т. Д. ... которое говорит мне, почему это работает так.

  • Какой-то обходной путь, поэтому мне не нужно иметь хранимую процедуру-обертку, и я могу просто выполнить то, что мне нужно, вызывая CLR SP непосредственно из C #.

1 Ответ

2 голосов
/ 01 декабря 2011

Странно.Попробуйте изменить код 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...