多个DbContext的存储库和工作单元模式的最佳实践

我计划使用ASP.NET MVC和Entity Framework 6(Code First / POCO)开发Web应用程序。 我还想在我的应用程序中使用通用存储库和工作单元模式。 此应用程序连接到两个以上的数据库,因此,我必须在应用程序中使用多个DbContext。

public class ContextOne : DbContext { public DbSet public DbSet } public class ContextTwo : DbContext { public DbSet public DbSet } public class ContextThree : DbContext { public DbSet public DbSet } public interface IRepository where T : DbContext { void Add(T entity) where T : class; } public class Repository where T : DbContext { void Add(T entity) where T : class { //T is DbContext and Model. So confusing } } public interface IUnitOfWork { } public class UnitOfWork { //IRepository contains more than one DbContext how can I initiate them here? } //in application should look like this public class BaseController : Controller { protected IRepository repository = new .. //here I have no idea with multiple DbContext } public class HomeController : BaseController { public ActionResult Add(Model_Two2 model) { base.repository.Add(model) } } 

如果我从Controller调用IRepository和IUnitOfWork,我怎么知道匹配的上下文? 这个问题的最佳实践是什么?

我建议你使用Constructor参数创建UnitOfWork模式以接受DbContext –

 public class UnitOfWork : IUnitOfWork { private readonly IDbContext _context; private bool _disposed; private Hashtable _repositories; public UnitOfWork(IDbContext context) { _context = context; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Save() { _context.SaveChanges(); } public virtual void Dispose(bool disposing) { if (!_disposed) if (disposing) _context.Dispose(); _disposed = true; } public IRepository Repository() where TEntity : class { if (_repositories == null) _repositories = new Hashtable(); var type = typeof(TEntity).Name; if (_repositories.ContainsKey(type)) return (IRepository) _repositories[type]; var repositoryType = typeof (Repository<>); var repositoryInstance = Activator.CreateInstance(repositoryType .MakeGenericType(typeof (TEntity)), _context); _repositories.Add(type, repositoryInstance); return (IRepository) _repositories[type]; } } 

其中IDbContext是 –

 public interface IDbContext { IDbSet Set() where T : class; int SaveChanges(); void Dispose(); } 

存储库实现将是 –

  public class Repository : IRepository where TEntity : class { internal IDbContext Context; internal IDbSet DbSet; public Repository(IDbContext context) { Context = context; DbSet = context.Set(); } public virtual TEntity FindById(object id) { return DbSet.Find(id); } public virtual void Update(TEntity entity) { DbSet.Attach(entity); } public virtual void Delete(object id) { var entity = DbSet.Find(id); var objectState = entity as IObjectState; if (objectState != null) objectState.State = ObjectState.Deleted; Delete(entity); } public virtual void Delete(TEntity entity) { DbSet.Attach(entity); DbSet.Remove(entity); } public virtual void Insert(TEntity entity) { DbSet.Attach(entity); } public virtual List GetAll() { return DbSet.ToList(); } } 

使用此方法,您可以为单个DBContext创建UnitOfWork,并且您具有在UnitOfWork中提交或回滚的特定逻辑。

我将UnitOfWork实现为ActionAttribute ,其中OnActionExecuting我打开事务,而OnActionExecuted我提交事务,如果一切正常,如果ActionContext有exception,则应该回滚事务。

棘手的是你有2个DbContexts。 我想,你应该懒得创建dbContexts。 引入一种标志变量并在UnitOfWork.OnActionExecuting中将其设置为True 。 然后,当您第一次触摸dbContext时,您应该检查是否正在处理UnitOfWork ,如果是,则应该为此特定dbContext打开事务。 可以将所有打开的事务放入可从UnitOfWork.ActionExecuted访问的List中。 最后,检查ActionContext中是否有任何exception:yes – Rollback ,no – Commit