Ленивый читает в замке.ActiveRecord - PullRequest
0 голосов
/ 22 января 2009

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

Поскольку таблица такая большая, я подозреваю, что когда я вызываю SomeObject.FindAll (), она читает все 1,4 миллиона строк и пытается вернуть все строки в SomeObject [].

Есть ли способ, которым я могу выполнить выражение SomeObject.FindAll (), но загрузить значения более удобным для СУБД способом?

1 Ответ

0 голосов
/ 22 января 2009

Не с FindAll() - который, как вы и предполагали, попытается загрузить все экземпляры указанного типа за один раз (и, в зависимости от того, как у вас настроен NHibernate, может выдать огромное количество SQL-запросы для этого).

Ленивая загрузка работает только со свойствами объектов, например, если у вас был постоянный тип SomeObjectContainer, у которого в качестве свойства был список SomeObject, сопоставленный таким образом, что он должен соответствовать всем SomeObject с и с lazy="true", затем с foreach в этом свойстве списка, вы получите то, что вы хотите, в некотором роде; по умолчанию NHibernate будет выдавать запрос для каждого элемента в списке, загружая только по одному за раз. Конечно, кэш-память чтения может вырасти, поэтому вам, вероятно, придется много сбрасывать.

Что вы можете сделать, это выполнить запрос HQL (или даже встроенный SQL), чтобы получить все идентификаторы для всех объектов SomeObject, а затем выполнить цикл по идентификаторам по одному, выбирая соответствующий объект с помощью FindByPrimaryKey. Опять же, это не особенно элегантно.

Если честно, в такой ситуации я бы, вероятно, превратил это в запланированное задание обслуживания в хранимом процессе - если только вам действительно не нужно запускать код на объекте, а не манипулировать данными , Это может раздражать пуристов объектов, но иногда хранимый процесс является правильным способом, особенно в сценарии пакетного задания такого типа.

...