Как передать byte[] из C# в виде строки в хранимую процедуру SQL Server и преобразовать в varbinary(MAX)

В этом проекте есть класс, обертывающий ADO.NET для общего доступа к данным, например ExecuteDataReader, ExecuteScalar и т. д.

При использовании этих методов для вызова хранимой процедуры он позволяет передать Dictionary<string, string> параметров (строковый ключ, строковое значение), которые затем добавляются к SqlCommand объекту как SqlParameter.

Есть случай, когда нам нужно сохранить документ в базе данных. Документ представляет собой byte[], а соответствующий столбец в базе данных — varbinary(MAX).

Мы искали решение, но все, что доступно, — это примеры использования SqlDbType.Varbinary, что не подходит в данной ситуации.

Нашей последней попыткой было преобразовать byte[] в двоичную строку, передать ее в хранимую процедуру как nvarchar(max), а затем использовать CONVERT(varbinary(max), @theFileBinaryString) при сохранении в таблице Document, однако при этом сохраняется поврежденный файл.

C#

byte[] pDocumentBytes = ...;
string documentAsBinary = "0x" + BitConverter.ToString(pDocumentBytes).Replace("-", ""); 

SQL

@DocumentContentAsBinary nvarchar(max) -- This is "documentAsBinary" from C# above

DECLARE @DocumentContentVarbinary varbinary(max);
SET @DocumentContentVarbinary = CONVERT(varbinary(max), @DocumentContentAsBinary);

person thiag0    schedule 26.05.2016    source источник


Ответы (3)


Предположим, у вас есть этот SP:

DECLARE
@Value1 ...
@Value2 ...
...
@File VARBINARY(MAX)

INSERT INTO [YourTable] (Column1, Column2, ..., File) VALUES (@Value1, @Value2, ..., @File)

Используйте этот синтаксис, чтобы преобразовать файл в массив байтов и напрямую вставить массив байтов как данные varbinary:

using System.Data.SqlClient;
using System.IO;

byte[] data;

using (FileStream fs = new FileStream(document, FileMode.Open)
{
    BinaryReader fileReader = new BinaryReader(document);
    data = fileReader.ReadBytes((int)document.Length);
    document.Close(); // don't forget to close file stream
}

using (var connection = new SqlConnection("YourConnectionStringHere"))
{
    connection.Open();
    using (var command = new SqlCommand("YourSPHere", connection)
    {
        command.CommandType = CommandType.StoredProcedure;

        // insert parameters here

        // add file parameter at the end of collection parameters
        command.Parameters.AddWithValue("@File", SqlDbType.VarBinary).Value = data;
        command.ExecuteNonQuery();
    }
    connection.Close();
}

Ссылка: http://www.codeproject.com/Questions/309795/How-to-insert-byte-array-into-SQL-table

Я надеюсь, что это решение полезно.

person Tetsuya Yamamoto    schedule 27.05.2016
comment
Спасибо за ответ. SP, который мы вызываем, принимает определяемый пользователем параметр таблицы, который принимает только содержимое документа как nvarchar(max). Нам нужно найти правильный способ передать это в SP как nvarchar(max), чтобы его можно было преобразовать в varbinary(max) внутри SP. - person thiag0; 27.05.2016

Обновите свой запрос, чтобы использовать параметры и передать массив байтов в качестве параметра непосредственно в таблицу.

например SQL:

insert into table values (@data);

C#

SqlComman com = new SqlCommand("insert into table values (@data);",Database Connection);
com.Paramaters.Add(new SqlParameter("@Data" Byte array));
com.executeNonQuery();
person Shon    schedule 26.05.2016
comment
Спасибо за ответ. К сожалению, у нас нет полного контроля над объектом SqlCommand, и нам приходится передавать файл как nvarchar(max). - person thiag0; 27.05.2016

Нет SqlDbType, который бы правильно отображался между VARBINARY(MAX) и byte[]. Но на самом деле это нормально, потому что инфраструктура параметризации просто обрабатывает это за вас, следующий код просто будет работать:

var binary = new bytes[1];
var command = new SqlCommand("INSERT INTO [MyTable]([BinaryColumn]) VALUES (@binary)");
command.Parameters.AddWithValue("@binary", binary);
command.ExecuteNonQuery();

Подробнее см. здесь: Что SqlDbType сопоставляется с varBinary(max)?

person satnhak    schedule 27.05.2016
comment
Спасибо за ответ. К сожалению, в этом сценарии это не сработает, так как мы должны передать содержимое документа как nvarchar(max), а затем преобразовать его в SP. - person thiag0; 27.05.2016
comment
Но почему? Преобразование в NVARCHAR, а затем обратное преобразование вообще не имеет смысла. Параметры вашей хранимой процедуры просто неверны и нуждаются в изменении. - person satnhak; 30.05.2016