Providing Factory and UnitOfWork with a type parameter can be a solution:
public class UnitOfWork<T> : IUnitOfWork<T> where T : DbContext, new() { private T _context; private readonly IDatabaseFactory<T> _databaseFactory; protected T Context { get { return _context ?? (_context = _databaseFactory.Get()); } } public UnitOfWork(IDatabaseFactory<T> factory) { _databaseFactory = factory; _context = _databaseFactory.Get(); }
The interfaces IDatabaseFactory and IUnitWork must also be shared.
Then you can create a Work Unit for different contexts:
var factory1 = new DatabaseFactory<SiteModelContainer>(); var unitOfWork1 = new UnitOfWork<SiteModelContainer>(factory1); var factory2 = new DatabaseFactory<AnotherModelContainer>(); var unitOfWork2 = new UnitOfWork<AnotherModelContainer>(factory2);
Edit:
To get rid of the EF dependency in your service classes, you can try something like this. The service knows only these three interfaces:
public interface IUnitOfWorkFactory { IUnitOfWork Create(string contextType); } public interface IUnitOfWork : IDisposable { IRepository<TEntity> CreateGenericRepository<TEntity>() where TEntity : class; void Commit(); } public interface IRepository<T> { IQueryable<T> Find(Expression<Func<T, bool>> predicate); void Attach(T entity); void Add(T entity);
Here are special implementations specific to EF:
public class UnitOfWorkFactory : IUnitOfWorkFactory { public IUnitOfWork Create(string contextType) { switch (contextType) { case "SiteModelContainer": return new UnitOfWork<SiteModelContainer>(); case "AnotherModelContainer": return new UnitOfWork<AnotherModelContainer>(); } throw new ArgumentException("Unknown contextType..."); } } public class UnitOfWork<TContext> : IUnitOfWork where TContext : DbContext, new() { private TContext _dbContext; public UnitOfWork() { _dbContext = new TContext(); } public IRepository<TEntity> CreateGenericRepository<TEntity>() where TEntity : class { return new Repository<TEntity>(_dbContext); } public void Commit() { _dbContext.SaveChanges(); } public void Dispose() { _dbContext.Dispose(); } } public class Repository<T> : IRepository<T> where T : class { private DbContext _dbContext; private DbSet<T> _dbSet; public Repository(DbContext dbContext) { _dbContext = dbContext; _dbSet = dbContext.Set<T>(); } public IQueryable<T> Find(Expression<Func<T, bool>> predicate) { return _dbSet.Where(predicate); } public void Attach(T entity) { _dbSet.Attach(entity); } public void Add(T entity) { _dbSet.Add(entity); }
Your service will receive IUnitOfWorkFactory :
public class MyService { private IUnitOfWorkFactory _factory; public MyService(IUnitOfWorkFactory factory) { _factory = factory; } public MyMethod() { using(var unitOfWork1 = _factory.Create("SiteModelContainer")) { var repo1 = unitOfWork1. CreateGenericRepository<SomeEntityTypeInSiteModel>();
When a service is created, a specific Factory instance is entered:
var service = new MyService(new UnitOfWorkFactory());
Keep in mind that the hard work will be in the abstract repository and its implementation. Once you no longer have the EF context in the service class, you must imitate the many methods in the repo interface that supports all the necessary scripts for managing data.