我计划使用带有Entity Framework 6(Code First / POCO)的ASP.NET MVC开发Web应用程序。我还想在我的应用程序中使用通用存储库和工作单元模式。此应用程序连接到两个以上的数据库,因此,我必须在应用程序中使用多个DbContext。
public class ContextOne : DbContext
{
public DbSet<Model_One1>
public DbSet<Model_One2>
}
public class ContextTwo : DbContext
{
public DbSet<Model_Two1>
public DbSet<Model_Two2>
}
public class ContextThree : DbContext
{
public DbSet<Model_Three1>
public DbSet<Model_Three2>
}
public interface IRepository<T> where T : DbContext
{
void Add<T>(T entity) where T : class;
}
public class Repository<T> where T : DbContext
{
void Add<T>(T entity) where T : class
{
//T is DbContext and Model. So confusing
}
}
public interface IUnitOfWork<IRepository>
{
}
public class UnitOfWork<IRepository>
{
//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_Two2>(model)
}
}
如果我从Controller调用IRepository和IUnitOfWork,我怎么知道匹配的上下文?这个问题的最佳做法是什么?
答案 0 :(得分:8)
我建议您使用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<TEntity> Repository<TEntity>() where TEntity : class
{
if (_repositories == null)
_repositories = new Hashtable();
var type = typeof(TEntity).Name;
if (_repositories.ContainsKey(type)) return (IRepository<TEntity>) _repositories[type];
var repositoryType = typeof (Repository<>);
var repositoryInstance =
Activator.CreateInstance(repositoryType
.MakeGenericType(typeof (TEntity)), _context);
_repositories.Add(type, repositoryInstance);
return (IRepository<TEntity>) _repositories[type];
}
}
其中IDbContext是 -
public interface IDbContext
{
IDbSet<T> Set<T>() where T : class;
int SaveChanges();
void Dispose();
}
存储库实现将是 -
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
internal IDbContext Context;
internal IDbSet<TEntity> DbSet;
public Repository(IDbContext context)
{
Context = context;
DbSet = context.Set<TEntity>();
}
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<TEntity> GetAll()
{
return DbSet.ToList();
}
}
使用这种方法,您可以为单个DBContext创建UnitOfWork,并且您具有在UnitOfWork中提交或回滚的特定逻辑。
答案 1 :(得分:0)
我会将UnitOfWork
实现为ActionAttribute
其中OnActionExecuting
我打开事务,OnActionExecuted
如果一切正常,我提交事务,如果{{1}中存在异常,应该回滚事务。
棘手的是你有2个DbContexts。我想,你应该懒得创建dbContexts。引入一种标志变量并将其设置为ActionContext
中的True
。然后,当您第一次触摸dbContext时,您应该检查是否正在处理UnitOfWork.OnActionExecuting
,如果是,则应该打开此特定dbContext的事务。所有未结交易都可以放入可从UnitOfWork
访问的列表中。最后,检查ActionContext中是否存在任何异常:是 - UnitOfWork.ActionExecuted
,否 - Rollback
。