NHibernate LazyInitializationException.. Как предотвратить?

Я получаю следующую ошибку на нашем веб-сервер:

NHibernate.LazyInitializationException
: 
Initializing[Domain.Entities.AudienceTypes.Region#4]-failed to lazily initialize a 
collection of role: Domain.Entities.AudienceTypes.Region.PeerGroups, 
no session or session was closed

что нехорошо. Единственный способ заставить приложение работать снова-сбросить IIS, что на самом деле не является вариантом. Что это значит? Как я могу предотвратить это?

4 ответов


отношения по умолчанию ленивы. Это означает, что SQL-запрос для загрузки связи выполняется только при доступе к свойству, который держит отношения.

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

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

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

References(x => x.PeerGroupId, "PeerGroupId").Fetch.Join();

добавлять Fetch.Join () предотвратит исключение LazyInitializationException.


Не закрывайте сеанс, пока не закончите работу с объектом.

Это одна из самых больших проблем работы с NHIbernate IMHO: определение границ сеанса.

в ASP.NET применение, это довольно просто: сеанс начинается в начале запроса, и вы можете закрыть сеанс в конце запроса.

в приложении WinForms это немного сложнее: вам придется четко определить границы, когда сеанс запускается, и когда сессия закрывается. В приложениях WinForms я обычно определяю "задачи", которые представляют собой некоторую единицу работы. Каждая задача имеет сеанс. Сеанс создается / открывается при создании задачи и закрывается после ее завершения.

рядом с этим вы также можете определить некоторые ассоциации как не ленивые. Тем не менее, вы должны убедиться, что производительность не влияет, если вы это сделаете.


далее к ответам Фредерика и лухопа, если вы работаете над ASP.NET приложение (как предложено вашим упоминанием веб-сервера), это хорошая идея использовать структуру инъекции зависимостей (например, Castle Windor) для обработки жизненного цикла ваших ISessions. Castle Windsor имеет стиль жизни "PerWebRequest", который делает это для вас.

в противном случае вручную создайте ISession в начале каждого запроса, который уничтожается (возможно, автоматически смывается) в конце запроса. Тогда ваше приложение может использовать этот ISession.

Это определенно связано с тем, что ISession закрывается, прежде чем вы думаете, что это так.