NHibernate: «не удалось лениво инициализировать ...», DDD подход - PullRequest
2 голосов
/ 21 сентября 2009

Я пытаюсь настроить NHibernate в приложении ASP.NET MVC, используя подход DDD. Тем не менее, я получаю сообщение об ошибке при попытке ленивой загрузки объекта, связанного с объектом. Вот как я структурировал свое приложение:

Уровень инфраструктуры: Содержит файлы сопоставления, реализации репозитория и загрузчик NHibernate для настройки и построения фабрики сеансов.

Вот пример репозитория:

public class CustomerRepository : ICustomerRepository
{
    public Customer GetCustomerById(int customerId)
    {
        using (var session = NHibernateBootstrapper.OpenSession())
            return session.Get<Customer>(customerId);
    }
}

Доменный слой: Имеет простые классы POCO, репозиторий и сервисные интерфейсы

Прикладной уровень: Содержит реализации службы.

Вот пример службы:

public class CustomerService : ICustomerService
{
    private ICustomerRepository _repository;

    public CustomerService(ICustomerRepository repository)
    {
        _repository = repository;
    }

    public Customer GetCustomerById(int customerId)
    {
        return _repository.GetCustomerById(customerId);
    }
}

Презентационный слой: Содержит приложение ASP.NET MVC. И здесь я обнаружил свою проблему. Используя подход MVC, у меня есть контроллер, который, используя службу CustomerService, получает клиента и отображает клиента в представлении (строго типизированный). У этого клиента есть связанный объект Contact, и когда я пытаюсь получить к нему доступ в своем представлении с помощью Model.Contact, где Model - это мой объект Customer, я получаю LazyInitializationException.

Я знаю, почему я это понимаю. Это связано с тем, что сеанс, используемый для извлечения Customer в CustomerRepository, уже мертв. Моя проблема в том, как я могу это исправить. Я хотел бы, если бы я мог избежать получения связанной сущности Контакта для Клиента в моем хранилище, потому что некоторые представления нуждаются только в данных Клиента, а не в Контактных данных. Если это вообще возможно?

Итак, вопрос: возможно ли подождать запросов к базе данных, пока уровень представления не будет нуждаться в связанном объекте Contact?

Я думаю, что мне нужно что-то вроде того, что описывает эта статья . Я просто не могу понять, как реализовать это на уровне инфраструктуры, или где это должно быть реализовано?

Заранее спасибо. Любая помощь будет высоко ценится!

Ответы [ 3 ]

2 голосов
/ 22 сентября 2009

Что касается управления сеансом, то обычно используется один сеанс на запрос. Вы можете увидеть пример реализации здесь . Это проект с открытым исходным кодом, предназначенный для настройки новых приложений asp.net с помощью Nhibernate. Исходный код можно найти здесь .

Надеюсь, это поможет.

1 голос
/ 22 сентября 2009

Я также рекомендую Sharp Architecture.

Другой подход, а также предложение, состоит в том, чтобы избегать передачи сущностей в представления. Есть и другие проблемы, кроме управления сессиями - бизнес-правила просачиваются в представления, раздутый код / ​​код spagetti и т. Д. Используйте подход ViewModel.

Другая проблема, которую вы получите, - это сохранение ваших сущностей в сеансе. Как только вы попытаетесь получить своего клиента из сеанса ["customer"], вы получите то же исключение. Для этого есть несколько решений, например, хранение идентификаторов или добавление методов репозитория для предотвращения отложенной загрузки объектов, которые вы собираетесь хранить в сеансе - прочитайте SetFetchMode в NHibernate - который, конечно, вы также можете использовать для передачи Просмотры. Но, как я уже сказал, вам лучше придерживаться подхода ViewModel. Google для ViewModel или обратитесь к книге ASP.NET MVC In Action, в которой используются примеры кода из http://code.google.com/p/codecampserver/. Также прочитайте это , например.

0 голосов
/ 22 сентября 2009

Все ваши свойства и методы в вашем классе Customer отмечены virtual?

Как вы открываете и закрываете сессию? Я использую ActionFilterAttribute под названием TransactionPerRequest и украшаю им все свои контроллеры.

Проверьте this для реализации.

...