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 закрывается, прежде чем вы думаете, что это так.