Медленное перечисление linq - PullRequest
1 голос
/ 22 сентября 2009

Я работал над приложением silverlight, которое генерирует различные графики. Это требует некоторого сокращения чисел, а также получения приличного количества данных из базы данных.

Для связи с БД я создал веб-сервис, который использует Linq2SQL. Чтобы преодолеть проблему взрыва моего веб-сервиса, я делю данные на части, что иногда приводит к 3 вызовам веб-сервиса, чтобы получить все это.

К вопросу. При получении больших объемов данных процесс перечисления " ToList () " занимает хорошие несколько секунд, что в целом увеличивает время загрузки. Типичная продолжительность моего запроса составляет около 1500 в соответствии с SQL Profiler. Вызов ToList () может занять до 4 секунд для 1000 записей, что кажется экстремальным.

Мой главный вопрос: можно ли что-нибудь сделать, чтобы ускорить этот процесс? Или, может быть, есть лучший способ получить большие объемы данных из базы данных в приложение silverlight?

Дополнительная информация:

Моя ссылка на linq жестко закодирована в частичный класс моего контекста данных. Это связано с неудобной хранимой процедурой, тип возвращаемой информации которой не подходит для файла dbml.

Я также создал базовый объект, который я установил в качестве возвращаемого типа для моего объекта, состоящий в основном из быстрых определений свойств, таких как:

 public Guid Id {get; set;} 

Следующий вопрос: при определении вызова хранимой процедуры и типов возврата linq, существуют ли какие-либо атрибуты, которые помогают ускорить процесс, или я в порядке, просто связав его с очень простым объектом?

Ответы [ 4 ]

0 голосов
/ 23 ноября 2009

Чтобы избежать необходимости использовать ToList (), попросите прокси-сервер веб-службы сгенерировать код, который использует коллекцию List. Сделайте это, найдя ссылку на сервис в вашем проекте Visual Studio. Щелкните правой кнопкой мыши> Configure Service Reference. Затем под типом коллекции выберите коллекцию, которая поддерживает методы linq. Я бы использовал System.Collection.Generic.List. Затем обновите ссылку на службу, чтобы восстановить файл References.cs.

0 голосов
/ 05 ноября 2009

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

0 голосов
/ 19 ноября 2009

Ответ - вообще прекратить использование ToList (). Не загружайте все свои данные в ваш веб-сервис, а затем отправляйте их обратно клиенту как один большой объект. Возьмите потоковый подход; поэтому вместо (псевдокод)

for each record in query;
  add record to list

for each record in list;
  create a line of response
  write line to response.

Разве вы не можете транслировать ответ как этот?

for each record in query;
  create a line of response
  write line to response.

foreach в вашем веб-сервисе должен последовательно просматривать результаты запроса по одной записи, и использование памяти будет абсолютно минимальным.

0 голосов
/ 23 сентября 2009

Сначала вам нужно выяснить, где находится узкое место; обычные преступники:

  • латентность; Вы упоминаете 3 звонков (а не 300), поэтому я не думаю, что это проблема
  • ширина полосы; насколько жирными являются объекты, которые вы хотите отправить
  • производительность ядра базы данных; как быстро ваш SELECT
  • проблемы с отложенной загрузкой; вы на самом деле делаете n + 1 дБ?

Изучите последние два с помощью трассировки SQL или некоторой простой регистрации (LINQ-to-SQL имеет свойство DataContext.Log, которое может быть очень полезно здесь); трассировка SQL может быть более точной.

Чтобы выяснить, является ли количество обращений от клиента Silverlight к веб-серверу проблемой, попробуйте выполнить трассировку сети; Fiddler или WireShark должны сделать эту работу.

Если проблема заключается в пропускной способности (т. Е. Огромном объеме данных по сети), то рассмотрите:

  • сжатие
  • другой сериализатор

Например, protobuf-сеть может сделать огромные различия с размером на проводе; хотя любой из них может потребовать немного другой код - самый простой подход - передать byte[] через службу (и, если возможно, использовать MTOM).

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