Создавайте и обслуживайте файл на сервере по требованию.Лучший способ сделать это, не потребляя слишком много ресурсов? - PullRequest
2 голосов
/ 26 августа 2011

Мое приложение должно экспортировать результат хранимой процедуры в формат .csv. По сути, клиент выполняет запрос, и он может видеть результаты в разбитой на страницы сетке, если она содержит то, что он хочет, затем он нажимает кнопку «Экспорт в CSV» и загружает все это.

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

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

Самый простой способ : вызвать хранимую процедуру с помощью LINQ, создать поток и выполнить итерацию по коллекции результатов и создать строку в файле для каждого элемента коллекции.

  1. Проблема 1: Относится ли отложенное выполнение также к LINQ для хранимых процедур? (Я имею в виду, будет ли .NET пытаться создать коллекцию со всеми элементами в наборе результатов в памяти? Или он выдаст мне результат за элементом, если я выполню итерацию вместо .ToArray?)

  2. Проблема 2. Сохраняется ли этот поток в оперативной памяти до тех пор, пока я не выполню .Dispose / .Close?

Не очень простой способ : вызывать хранимую процедуру с IDataReader и для каждой строки записывать непосредственно в поток ответов HTTP. Это похоже на хороший подход, пока я читаю, я пишу в ответ, память не взорвалась.

Это действительно того стоит?

Надеюсь, я правильно объяснил.

Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 10 сентября 2011

Запись в поток - это лучший способ, так как он будет потреблять не больше текущей «записи» и связанной с ней памяти.Этот поток может быть FileStream (если вы создаете файл) или поток ASP.NET (если вы пишете напрямую в Интернет), или любой другой полезный поток.

Преимущество создания файла (с использованиемFileStream) должен иметь возможность кэшировать данные для обслуживания одного и того же запроса снова и снова.В зависимости от ваших потребностей это может быть реальным преимуществом.Вы должны придумать интеллектуальный алгоритм, чтобы определить путь и имя файла по входным данным.Это будет ключ кеша.Получив файл, вы можете использовать API TransmitFile , который использует кеш ядра Windows и в целом очень эффективен.Вы также можете поиграть с клиентскими кешами HTTP (заголовками типа last-modified-since и т. Д.), Поэтому в следующий раз, когда клиент запросит ту же информацию, вы можете вернуть ответ not modified (код состояния HTTP 304).Недостатки использования файлов кэша в том, что вам нужно будет управлять этими файлами, дисковым пространством, сроком действия и т. Д.

Теперь Linq или IDataReader не должны сильно менять параметры перфорации или использования памяти, если вы не используете метод Linq.что материализуют целые данные (исчерпывают поток) или большую их часть.Это означает, что вам нужно избегать методов ToArray (), ToList () и других подобных методов, и концентрироваться только на «потоковых» методах (перечисления, пропуски, while и т. Д.).

1 голос
/ 09 сентября 2011

Я знаю, что опаздываю на игру здесь, но теоретически, сколько записей мы здесь говорим?Я видел, как накапливается 5000, и если это так, то это не должно быть проблемой для вашего сервера.

Ответ на самый простой способ:

  1. Да, если только выукажите иное (отключить отложенную загрузку).

  2. Не уверен, что я понимаю, что вы спрашиваете здесь.Вы имеете в виду потоковый ридер, который вы будете использовать для создания файла, или текстовый текст, который вы используете для вызова SP?Я полагаю, что после того, как вы закончите, текстовый текст будет очищен для вас (всегда хорошая практика, чтобы закрыть).Streamreader или тому подобное потребуется метод dispose для удаления из памяти.

Тем не менее, когда я имел дело с экспортом файлов, у меня был успех в предыдущем построении таблицы (CSV)программно (через итерацию), затем отправляя структурированные данные в виде HTTP-ответа с типом, указанным в заголовке, не так просто, как вы так красноречиво заявили :).Вот вопрос, который спрашивает, как сделать это с CSV:

Тип содержимого ответа как CSV

0 голосов
/ 26 августа 2011

То, о чем вы говорите, на самом деле не отложенное выполнение, а ограничение результатов запроса.Когда вы говорите objectCollection.Take(10), SQL, который генерируется при итерации перечислимого, принимает только первые 10 результатов этого запроса.

При этом хранимая процедура будет возвращать любые результаты, которые вы возвращаете,его 5 или 5000 строк данных.Выполнение .Take () для результатов не будет ограничивать то, что возвращает база данных.

Поэтому я рекомендую (если это возможно для вашего сценария) добавить параметры подкачки в вашу хранимую процедуру (номер страницы, размер страницы).Таким образом, вы будете возвращать только те результаты, которые планируете использовать.Затем, когда вам нужен полный список для вашего CSV, вы можете либо передать большой размер страницы, либо иметь значения NULL, означающие «Выбрать все».

0 голосов
/ 26 августа 2011

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

Возможно, нет, но я верю, что вам понадобится Silverlight ...

Вы можете настроить веб-сервис или контроллер, который позволяет извлекать данные «по странице» (очень похоже на простой вызов «пейджинговой» службы с использованием GridView или другого ретранслятора). Вы можете выполнять асинхронные вызовы из silverlight, чтобы получить каждую «страницу» данных до завершения, а затем использовать SaveFileDialog для сохранения на жесткий диск.

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

Пример 1 | Пример 2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...