Después de haber creado una pequeña aplicación utilizando el patrón de unidad de trabajo/repositorio, me cuesta entender cómo usar esto correctamente en mi capa de negocios. Mi aplicación tiene una capa de acceso a datos que puede ser NHibernate o Entity Framework. Puedo cambiar entre estos fácilmente.¿Cuál es la forma correcta de usar la Unidad de trabajo/Repositorios dentro de la capa empresarial?
Tengo varios repositorios, por ejemplo, Cliente, Orden, etc. Mi unidad de trabajo será una ISesión o un Contexto de Objeto dependiendo de con qué DAL quiero probar.
Mi capa empresarial contiene un único método de negocio - CreateOrder(). Lo que estoy luchando por comprender es en qué parte de la capa empresarial debería estar inicializando mi unidad de trabajo y mis repositorios.
Centrándose en Nhibernate, mi DAL parece:
public class NHibernateDAL : IUnitOfWork
{
log4net.ILog log = log4net.LogManager.GetLogger(typeof(NHibernateDAL));
ISession context;
public NHibernateDAL()
{
context = SessionProvider.OpenSession();
this.Context.BeginTransaction();
CurrentSessionContext.Bind(context);
}
public ISession Context
{
get { return context; }
}
public void Commit()
{
this.Context.Transaction.Commit();
context.Close();
}
public void Dispose()
{
ISession session = CurrentSessionContext.Unbind(SessionProvider.SessionFactory);
session.Close();
}
}
Dentro de mi capa de negocio, quiero saber dónde debería estar declarando mi unidad de trabajo y repositorios. ¿Están declarados a nivel de clase o dentro del método CreateOrder?
Por ejemplo:
public class BusinessLogic
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
NhRepository<Order> _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = new NhRepository<Customer>(_unitOfWork);
....
public void CreateOrder(.....)
{
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
El código anterior sólo funciona por primera vez el método createOrder() se llama, pero no para las llamadas posteriores debido a que la sesión se cierra. He intentado eliminar la llamada 'context.Close()' después de confirmar la transacción, pero esto también falla. Aunque el enfoque anterior no funciona, me parece más correcto declarar mis repositorios y unidad de trabajo con este alcance.
Sin embargo, si lo implemento de la siguiente manera, en cambio funciona bien, pero parece antinatural declarar los repositorios y la unidad de trabajo dentro del alcance del método en sí. Si tuviera una tonelada de métodos de negocio entonces estaría declarando repositorios y unidades de trabajo por todo el lugar:
public class BusinessLogic
{
public void CreateOrder(.....)
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
var _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = null;
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
Si tuviera que aplicar esto con declaración de nivel de clase, entonces creo que necesitaría algún medio de re -Abrir la misma unidad de trabajo al comienzo del método CreateOrder.
¿Cuál es la forma correcta de usar la unidad de trabajo y los repositorios dentro de la capa empresarial?