2010-12-30 2 views
3

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

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

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

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

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

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

+0

В какой версии вы принимаете? Рекомендуется использовать Filestream, а не хранить в виде блоков в файлах данных большие данные. –

+0

@Martin - * what * Filestream? ваш комментарий не очень полезен без дальнейшей проработки. –

+0

@Peter http://technet.microsoft.com/en-us/library/bb933993.aspx –

ответ

2

Вы можете передавать данные на диск, а затем использовать OPENROWSET для выполнения массового импорта данных. Не Например:

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

Вы можете использовать temp file APIs, чтобы избежать необходимости управлять временем жизни данных на диске ... он будет удален один раз больше не используется.

+0

Не уверен, что это будет эффективно, если IIS и SQL Server будут развернуты в разных блоках, так как мне нужно будет сохранить файл в общем доступе. – DSO

+1

Это то, что поддерживает FileStream в SqlServer. Клиент передает данные через SMB на сервер sql, сервер sql управляет данными везде, где он настроен для его хранения. Плюсом вам не нужно будет сохранять файл на веб-сервере, а затем переносить его на сервер sql. Сервер Sql также управляет безопасностью «на лету» на основе правил сервера sql. Недостатком является то, что вы должны разрешить windows auth и не имеете ограничений на брандмауэр между вашим веб-сервером и сервером sql для SMB. –

1

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

INSERT INTO XrayImages (HeaderId, ImageBytes) ЗНАЧЕНИЯ (@headerId, @imageValue)

UPDATE XrayImages SET ImageBytes.WRITE (@imageChunk, NULL, @chunkLength ГДЕ ImageID = @imageId;

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


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

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

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

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

+0

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

+0

Быстрое возможное тестирование - сделать загрузку, установив точку прерывания на ранней стадии действия контроллера. Посмотрите, будет ли использование памяти (вероятно, использование IIS вместо сервера веб-разработки) увеличиваться по размеру загрузки. Использование большего файла сделает это более очевидным. –

Смежные вопросы