Правильное использование шаблона NHibernate Unit Of Work и Ninject - PullRequest
15 голосов
/ 24 ноября 2010

У меня есть следующая реализация, и я хотел бы получить отзыв о том, правильно ли он использует NHibernate для сеансов и транзакций.пример использования:

public class Repository : IRepository
{
    private readonly ISessionFactory _sessionFactory;

    public Repository(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    public void Add(IObj obj)
    {
        using (var unitOfWork = new UnitOfWork(_sessionFactory))
        {
            unitOfWork.CurrentSession.Save(obj);
            unitOfWork.Commit();
        }         
    }
}

В моей предыдущей реализации я вставлял IUnitOfWork в конструктор репозитория, например,

public Repository(IUnitOfWork unitOfWork)
    {...

Но метод Dispose () не выполнялся, вызывая последующий вызоввыдать это исключение: «Не удается получить доступ к удаленному объекту. Имя объекта:« AdoTransaction ».»

Ответы [ 3 ]

35 голосов
/ 24 ноября 2010

Первое наблюдение: ваш репозиторий не должен фиксировать единицу работы.Это побеждает весь смысл единицы работы.Немедленно сохраняя свои изменения в репозитории, вы «микроуправляете» сессией NHibernate.

Единица работы должна указываться выше в стеке на уровне приложения / службы.Это позволяет вам иметь код приложения, который выполняет несколько действий, возможно, в разных репозиториях, и все же в конце фиксирует все сразу.

Сам класс UnitOfWork выглядит нормально, хотя вы должны спросить себя, действительно ли он вам нужен.В NHibernate ISession - это ваша единица работы.Ваш класс UnitOfWork, кажется, не добавляет много значения (тем более, что вы все равно выставляете свойство CurrentSession)

Но вам нужно подумать о его времени жизни.Я думаю, что вы ошибаетесь в этом вопросе.Управление временем жизни сеанса зависит от типа приложения, которое вы разрабатываете: в веб-приложении вам обычно требуется единица работы для каждого запроса (вы можете использовать Google для «сеанса nhibernate для каждого запроса»).В настольном приложении это немного сложнее, в большинстве случаев вам понадобится «сеанс на экран» или «разговор на бизнес-транзакцию».

8 голосов
/ 25 ноября 2010

У меня в основном приложение типа CRUD, и я реализовал шаблон Unit Of Work with Repository, но не смог уйти от разделения Session / Transaction.Сессии и транзакции требуют разных времен жизни.В настольном мире Сессия обычно «на экран», а Транзакция - «на действие пользователя».

Дополнительная информация в этой превосходной статье .

В итоге я получил:

  • IUnitOfWork -> Сессия Wraps, реализует IDisposable
  • IAtomicUnitOfWork -> Транзакция Wraps, реализует IDisposable
  • IRepository -> Обеспечивает получение, сохранение, удаление и запрос доступа

Я сделал так, что вам нужно IUnitOfWork для построения IAtomicUnitOfWork и вам IAtomicUnitOfWork построить IRepository, чтобы обеспечить надлежащее управление транзакциями.Это действительно все, что я получил, реализовав свои собственные интерфейсы.

Как сказал jeroenh, вы почти так же хорошо можете использовать ISession и ITransaction, но в конце я почувствовал себя немного лучше, написав весь свой код противинтерфейс, который я определил.

3 голосов
/ 25 ноября 2010

Важной частью ответа является то, что вы хотите, чтобы ваши размеры транзакций. Прямо сейчас (как указал jeroenh) транзакция выполняется для каждого вызова метода в вашем хранилище. Это очень мало и, вероятно, не нужно. Я создал приложение ASP.MVC, и оно использует размер транзакции, который включает в себя все, начиная с одного http-запроса. Это может быть несколько операций чтения / обновления базы данных. Я использую ту же единицу работы и Ninject для МОК. Посмотрите, может быть, что-то поможет с вашими проблемами:

http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/

http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

http://bobcravens.com/2010/09/the-repository-pattern-part-2/

http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/

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

Bob

...