Можно ли получить ленивый IEnumerable из запроса NHibernate, используя ICriteria?

Я работаю с NHibernate и мне нужно извлечь и обработать до 2 миллионов строк. В идеале я мог бы обрабатывать каждую строку - по одной за раз - без загрузки NHibernate сразу всех 2 миллионов в памяти (потому что, как вы знаете, это больно).

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

Возможно ли это с помощью ICriteria NHibernate? Все, что он возвращает, похоже на IList и полностью загружено перед передачей ссылки на коллекцию. Почему IList вместо IEnumerable ?!

Я не имею в виду «ленивый» в традиционном смысле, который NHibernate использует в отношении загрузки дочерних или родительских объектов. Я хочу, чтобы ленивый IEnumerable каким-то образом означал получение IEnumerable из объекта ICriteria . ICriteria имеет только метод List (), который загружает результаты в ArrayList.

12.12.2008 14:29:45
Я думал, что когда вы выполняете ленивый IEnumerable в NHibernate, вы начинаете запрашивать базу данных по одной строке за раз. Возможно, было бы проще перейти к хранилищу данных ADO.Net, если вам приходится иметь дело с таким количеством строк.
Min 12.12.2008 18:45:44
3 ОТВЕТА
РЕШЕНИЕ

У ICriteria нет методов, которые возвращают IEnumerable, но у IQuery есть .

1
12.12.2008 17:57:24
Есть ли способ преобразовать ICriteria в IQuery?
TheSoftwareJedi 12.12.2008 18:35:05
AFAIK IQuery для HQL и SQL (строковые запросы), а ICriteria - это ... ну, Критерии, я не вижу никаких мостов между ними. Я нахожу странным, что ICriteria не реализует Enumerate ...
Mauricio Scheffer 12.12.2008 20:24:15
Я тоже. Я использую код Linq-NHibernate от NContrib, и они реализуют с использованием ICriteria (после просмотра их кода). Я постараюсь исправить их дерьмо. Любая идея, когда NHibernate будет официально поддерживать Linq (я знаю, что его начало здесь).
TheSoftwareJedi 12.12.2008 20:47:09
Официальная поддержка Linq появится в версии 2.1.
Mauricio Scheffer 12.12.2008 22:17:55

То, что вы хотите сделать, это обернуть ваш доступ к данным таким способом:

public IEnumerable<YourObject> GetALotOfRows() {
  ..execute DataReader
  while(..read..) {
    yield return yourObject;
  }
}

Теперь у вас нет под рукой VS или nHibernate, так что извините за полупсевдокод. Но ключ здесь заключается в том, чтобы использовать «возврат прибыли».

0
12.12.2008 14:39:22
Я считаю, что оператор выполнения NHibernate делает его не таким ленивым, как хотел OP.
user7116 12.12.2008 14:42:36
Когда ОП сказал LAZY, я думаю, он имел в виду что-то вроде того, что делает SqlDataReader.
Strelok 12.12.2008 14:53:57
Это то, чего я хочу, но я хочу знать, как заставить NHibernate сделать это для меня или, по крайней мере, поддержать его. NHibernate вручает мне IList .... На самом деле, я использую Linq для NHibernate (от NContrib), но это, похоже, не имеет значения ....
TheSoftwareJedi 12.12.2008 15:06:52

Что это за операция, которую нужно делать построчно? Мне просто любопытно :).

Вы можете попытаться просмотреть результаты - получить первые 10, следующие 10 ... и так далее.

РЕДАКТИРОВАТЬ: Таким образом, вы бы

Session.CreateCriteria(typeof(T)).SetFirstResult(0).SetMaxResults(1).UniqueResult<T>();
Session.CreateCriteria(typeof(T)).SetFirstResult(1).SetMaxResults(1).UniqueResult<T>();
Session.CreateCriteria(typeof(T)).SetFirstResult(2).SetMaxResults(1).UniqueResult<T>();

Вы понимаете, я думаю, что это не лучший способ, это не IEnumerable ... но это сработает. Вы также можете сделать SetMaxResults (10) или что-то большее, чтобы не отправлять 1 за раз.

0
12.12.2008 17:19:53
Как бы я страницу результатов? Я делаю потоковую передачу результатов обратно клиенту HTTP в виде файла CSV. Я уже реализовал CSVStream, и он будет поддерживать преобразование и запись по одной записи за раз. Мне просто нужно NHibernate, чтобы сделать это тоже. ИЗ ИКРИТЕРИИ. :)
TheSoftwareJedi 12.12.2008 17:08:52
Нет способа получить IEnumerable из ICriteria.
Mauricio Scheffer 12.12.2008 17:57:46