ПРАВИЛЬНОЕ ИСПОЛЬЗОВАНИЕ НИБЕРНИТАЦИОННОГО РАЗДЕЛА РАБОТА И НИНЖЕНИЯ

StackOverflow https://stackoverflow.com/questions/4271265

Вопрос

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

public interface IUnitOfWork : IDisposable
{
    ISession CurrentSession { get; }
    void Commit();
    void Rollback();
}

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        CurrentSession = _sessionFactory.OpenSession();
        _transaction = CurrentSession.BeginTransaction();
    }

    public ISession CurrentSession { get; private set; }

    public void Dispose()
    {
        CurrentSession.Close();
        CurrentSession = null;
    }

    public void Commit()
    {
        _transaction.Commit();
    }

    public void Rollback()
    {
        if (_transaction.IsActive) _transaction.Rollback();
    }
}

Привязка Ninject

Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope();
Bind<IRepository>().To<Repository>().InTransientScope();

Вот пример использования:

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();
        }         
    }
}

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

public Repository(IUnitOfWork unitOfWork)
    {...

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

Это было полезно?

Решение

Первое наблюдение: Ваш репозиторий не должен совершать единицу работы. Это поражает всю точку единицы работы шаблона. Сразу же спасая свои изменения в репозитории, вы «Micro Managing» Nhibernate Session.

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

Сам уединенный класс UnitOFWork выглядит хорошо, хотя вы должны спросить себя, действительно ли вам это нужно. В Nibernate Isessess - ваша единица работы. Ваш класс UnitOfWork не добавляет большого значения (тем более, что вы в любом случае вы обнажили свойство CurrentSessions

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

Другие советы

У меня в основном в основном тип приложения Crud, и я реализовал единицу работы с рисунком репозитория, но не мог уйти вдали от сеанса / транзакции. Сеансы и транзакции нуждаются в разных жизненных жизни. В настольном настольном мире сеанс обычно «на экран», а транзакция - «Per-User-Action».

Больше информации в этом Отличная статья.

Так что я оказался:

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

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

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

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

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

http://bobcravens.com/2010/07/using-nibernate-in-ass-net-mvc/

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

http://bobcravens.com/2010/11/using-ninject-to-manage-criitic-rusources/

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

Боб

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top