Как передавать большие двоичные данные на SQL Server - PullRequest
3 голосов
/ 30 декабря 2010

У меня есть веб-сервис, написанный на ASP.NET MVC с бэкэндом SQL Server. Клиенты могут отправлять большие данные во время звонков в веб-службу, порядка 10 мегабайт каждый.

На стороне сервера я хочу прочитать поток HTTP-запросов и записать его в поле VARBINARY в таблице SQL. Как я могу сделать это, не считывая весь поток в массив в памяти ?

Причина, по которой меня беспокоит память, заключается в том, что этой системе необходимо масштабировать до 1000 одновременных клиентов (по крайней мере).

В настоящее время я использую Linq to SQL, и похоже, что он не поддерживает потоковую передачу данных, поскольку двоичный тип Linq можно инициализировать только с помощью байтового массива.

Есть ли другой способ сделать это с помощью Linq to SQL?

Если это невозможно с использованием Linq to SQL, как я могу сделать это с помощью ADO.NET или другого подхода?

Ответы [ 2 ]

2 голосов
/ 30 декабря 2010

Вы можете выполнить потоковую передачу данных на диск, а затем использовать OPENROWSET , чтобы выполнить массовый импорт данных. Например:

INSERT INTO YOURTABLE(binaryColumnName) 
SELECT * FROM 
OPENROWSET(BULK N'C:\data.bin', SINGLE_BLOB)

Вы можете использовать API временных файлов , чтобы избежать необходимости управлять временем жизни данных на диске ... они будут удалены, когда они больше не будут использоваться.

1 голос
/ 04 января 2011

Я полагаю, что вы можете использовать предложение .WRITE инструкции UPDATE для вставки фрагментированных данных. Если вы используете LINQ, вы должны создать две команды из объекта контекста данных. Сначала создайте (INSERT) строку, которая будет содержать данные. Второй будет оператор UPDATE, который использует предложение .WRITE. параметризовать данные и значения смещения. Выполните цикл, выполняя инструкцию UPDATE столько раз, сколько у вас есть «чанков».

ВСТАВИТЬ В XrayImages (HeaderId, ImageBytes) ЗНАЧЕНИЯ (@headerId, @imageValue)

ОБНОВЛЕНИЕ XrayImages SET ImageBytes.WRITE (@imageChunk, NULL, @chunkLength WHERE ImageId = @imageId;

Для получения дополнительной информации, пожалуйста, ознакомьтесь с этой статьей MSDN: http://msdn.microsoft.com/en-us/library/bb399384.aspx


Я почти уверен, что к тому времени, когда будет вызван ваш код контроллера, весь запрос будет получен (и будет в памяти). Я основываюсь на том, что коллекция Request.Files уже знает, сколько там файлов и какова их длина. Для форм, состоящих из нескольких частей, единственный способ узнать, как это определить, - прочитать весь запрос. В любом случае я не знаю, как это изменить в MVC, поэтому вам, возможно, придется написать обработчик, который сам выполняет фактическую загрузку файла.

Здесь много переменных, которые необходимо учитывать. В зависимости от количества тысяч одновременно работающих клиентов, которые будут загружать данные одновременно, вам понадобится несколько гигабайт между сервером db и веб-сервером. Вам также понадобятся возможности ввода / вывода на вашем сервере баз данных, которые будут выше того, что я испытал.

Я бы серьезно подумал о сохранении файлов в расположении на основе файловой системы и наличии метаинформации в базе данных, особенно если вы можете хранить файлы на веб-сервере. В противном случае, я думаю, что использование возможностей FileStream от SqlServer было бы более масштабируемым, чем просто решение для таблиц.

Надеюсь, это поможет!

...