My current application structure is:
Data.IRepository<>
to ORM.GenericRepository<>
IRepository<>
This structure has essentially decoupled the Business layer from the ORM implementing the IRepository<T>
.
One of the benefits of this decoupled structure is that I should be able to replace the ORM relatively easily - for example, move from Entity Framework to NHibernate or just upgrading an existing ORM. I'm currently using EF 4.1 code first and am building another assembly for NHibernate.
I'm considering implementing the Unit of Work pattern.
I've read that this pattern should be used in the business layer (with interfaces defined in my Data assembly, and implemented in the ORM assembly just like I did with the repository pattern). Currently, all instantiated repositories have their own DbContext / session and its lifetime is set to that of the repository - which may be bad- my problem is that I'm not sure if its possible to implement a Unit of Work pattern that would work with different ORM's (er rather, it probably is and I'm just not up to speed).
This is the only thing that comes to mind:
Create IUnitOfWork in my Data assembly that has a function: object GetCurrentSession();
, then have an argument in the constructor of the repositorys in the ORM assembly and cast it to the appropriate session / DbContext (If NHibernate then ISession, if Entity Framework then DbContext)
I would appreciate if anyone has some insight into this situation.
I may have found a solution (have not tried it yet):
In the Data assembly:
public interface IUnitOfWork : IDisposable
{
void Start();
T Current<T>();
// IDisposable stuff
}
In the ORM assembly:
public class GenericRepository<T> : IRepository<T>
where T : PersistentEntity
{
private ISession CurrentSession;
public GenericRepository(IUnitOfWork uow)
{
CurrentSession = uow.Current<ISession>();
}
// other repository stuff here
}
public class NHhibernateUnitOfWork : IUnitOfWork
{
private ISession CurrentSession;
public void Start()
{
// instantiate CurrentSession
}
T Current<T>()
{
if(typeof(T) is ISession)
return (T)CurrentSession;
else
return new NotImplementedException();
}
}
// in the prism module
container.Resolve(typeof(IUnitOfWork), typeof(NHhibernateUnitOfWork));
In the Business assembly:
IUnitOfWork uow = container.Resolve<IUnitOfWork>();
using(uow.Start())
{
IRepository custRepo = container.Resolve<IRepository<Customer>>(uow);
// do stuff here with cust repo
}
This is just a proof of concept of decoupling IUnitOfWork from the concrete implementation.