Результаты запроса не могут быть перечислены более одного раза?
Я использую LINQ to SQL, чтобы получить результат поиска хранимой процедуры FullTextSearch на сервере Sql 2008. Я перетащил процедуру из проводника сервера в конструктор и получил метод, созданный с соответствующим типом возвращаемого значения и параметрами. Теперь проблема в том, что мне нужно получить граф результата вызова этого метода, поэтому, используя мой метод репозитория (который вызовет метод Sproc и вернет результат как IQueryable), я делаю следующий вызов.
var result = repository.FullTextSearch(searchText);
int resultsCount = result.Count();
var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList();
Этот код генерирует InvalidOperationException каждый раз, когда я пытаюсь его запустить, исключение говорит (да, вы уже догадались!) "Результаты запроса не могут быть перечислены более одного раза".
Метод, который был сгенерирован для Sproc, возвращает ISingleResult, который должен быть O.K. НАСКОЛЬКО МНЕ ИЗВЕСТНО. Мне нужно поддерживать пейджинг на моем представлении, поэтому мне нужно знать общее количество страниц, которое (AFAIK снова) возможно только в том случае, если я могу получить количество всех элементов.
Чего мне здесь не хватает, ребята?
Ответы
Ответ 1
Так как это выполняет хранимую процедуру, все ваши прекрасные Skip
/Take
в любом случае являются избыточными... у него нет выбора, кроме как вернуть все данные (вызовы хранимых процедур не являются составными). Единственное, что он может сделать, это не материализация объектов для некоторых из них.
Интересно, будет ли лучший подход реорганизовать код для совершения двух вызовов:
int result = repository.FullTextSearchCount(searchText);
var result = repository.FullTextSearch(searchText, skip, take); // or similar
то есть. сделать параметры поискового вызова частью SPROC (и фильтрации в базе данных с помощью ROW_NUMBER()
/OVER(...)
или табличных переменных, temp-таблиц и т.д.) - или, альтернативно, что-то похожее с параметром OUTPUT
в sproc:
int? count = null;
var result = repository.FullTextSearch(searchText, skip, take, ref count);
(Кажется, я помню, что OUTPUT
становится ref
, поскольку TSQL OUTPUT
действительно вводит + вывод)
Ответ 2
Что вы можете сделать, это добавить вызов ToList()
после repository.FullTextSearch(searchText)
. Таким образом, результаты извлекаются с сервера, после чего вы можете делать с ними все, что хотите (поскольку они теперь загружаются в память).
Теперь вы пытаетесь выполнить один и тот же SQL-запрос дважды, что довольно неэффективно.
Ответ 3
Использование ToList()
может помочь избежать этой проблемы.
var result = repository.FullTextSearch(searchText).ToList();
Ответ 4
Я бы предположил, что если вам нужен счет, сначала выполните результат. а затем запустите счет из самого списка, так как вы не используете resultsCount в своем выполнении результата.
var result = repository.FullTextSearch(searchText);
var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList();
int resultsCount = ret.Count();