ПРАВИЛЬНОЕ ИСПОЛЬЗОВАНИЕ НИБЕРНИТАЦИОННОГО РАЗДЕЛА РАБОТА И НИНЖЕНИЯ
-
28-09-2019 - |
Вопрос
У меня есть следующая реализация и хотелось бы некоторую отзыв о том, будет ли это правильное использование 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/
Надеюсь это поможет.
Боб