C# N层应用程序中的多DBContext
我正在创建我的第一个N层MVC应用程序,在如何使用数据库优先的方法管理多个C# N层应用程序中的多DBContext,c#,entity-framework-4.1,repository,dbcontext,unit-of-work,C#,Entity Framework 4.1,Repository,Dbcontext,Unit Of Work,我正在创建我的第一个N层MVC应用程序,在如何使用数据库优先的方法管理多个dbContext方面遇到了一个障碍 我有以下几层 Presentation Service (WCF) Business Data Access 我不想在我的服务层中使用实体框架引用,但我不知道如何创建一个接口或其他东西来管理两个上下文。我在IDatabaseFactory中处理一个扭曲的上下文,但似乎找不到一种方法来管理两个 下面是我的UnitOfWork,它是在我的服务中创建的,但从各个角度看,我仍然与SiteMo
dbContext
方面遇到了一个障碍
我有以下几层
Presentation
Service (WCF)
Business
Data Access
我不想在我的服务层中使用实体框架引用,但我不知道如何创建一个接口或其他东西来管理两个上下文。我在IDatabaseFactory中处理一个扭曲的上下文,但似乎找不到一种方法来管理两个 下面是我的
UnitOfWork
,它是在我的服务中创建的,但从各个角度看,我仍然与SiteModelContainer
绑定在一起,而实际上我有另一个上下文
public class UnitOfWork : IUnitOfWork
{
private SiteModelContainer _context;
private readonly IDatabaseFactory _databaseFactory;
protected SiteModelContainer SiteContext
{
get { return _context ?? (_context = _databaseFactory.Get()); }
}
public UnitOfWork(IDatabaseFactory factory)
{
_databaseFactory = factory;
_context = _databaseFactory.Get();
}
//More code
}
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private SiteModelContainer _dataContext;
public SiteModelContainer Get()
{
return _dataContext ?? (_dataContext = new SiteModelContainer());
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
您可以创建一个包装器,它是跨DBContext的通用存储库(并利用底层ObjectContext来支持这一点) 这里是我在过去使用过的一个示例(它还将您的代码从对实体框架的任何直接依赖中分离出来)
//使您的DbContext从此继承。这是在你的工作单位。
公共接口IEntySetProvider:IDisposable
{
IEntitySet CreateEntitySet();
}
//这是你的背景
公共类MyDbContext1:DbContext,IEntySetProvider
{
公共IEntitySet CreateEntitySet()
{
返回新的EntitySet(((IObjectContextAdapter)this).CreateObjectSet());
}
.
.
.
}
///
///IQueryable的包装器,公开AddNew和Attach方法。
///
///
公共接口IEntitySet:IQueryable
{
///
///附加指定的值并将其视为新值。
///
///价值。
void AddNew(T值);
///
///附加指定的值并将其视为已修改。
///
///价值。
空隙附着(T值);
}
///
///实体框架的IEntitySet。
///
///
内部类EntitySet:EntitySet,其中T:class
{
私有只读对象集\u对象集;
公共实体集(ObjectSet ObjectSet)
{
_objectSet=objectSet;
}
#区域IEntitySet成员
公共void AddNew(T值)
{
_objectSet.AddObject(值);
}
公共空间附加(T值)
{
_objectSet.Attach(值);
_objectSet.Context.ObjectStateManager.ChangeObjectState(值,EntityState.Modified);
}
公共IEnumerator GetEnumerator()
{
return((IQueryable)u objectSet.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return((IQueryable)u objectSet.GetEnumerator();
}
公共类型ElementType
{
获取{return((IQueryable)u objectSet.ElementType;}
}
公开表达
{
获取{return((IQueryable)u objectSet.Expression;}
}
公共IQueryProvider提供程序
{
获取{return((IQueryable)\u objectSet.Provider;}
}
#端区
}
为Factory和UnitOfWork提供泛型类型参数可能是一种解决方案:
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();
}
//More code
}
public class DatabaseFactory<T> : Disposable, IDatabaseFactory<T>
where T : DbContext, new()
{
private T _dataContext;
public T Get()
{
return _dataContext ?? (_dataContext = new T());
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
编辑:
为了摆脱服务类中对EF的依赖,您可以尝试以下方法。服务只知道这三个接口:
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);
// etc.
}
创建服务时,将注入工厂的具体实例:
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>();
// Do some work
unitOfWork1.Commit();
}
using(var unitOfWork2 = _factory.Create("AnotherModelContainer"))
{
var repo2 = unitOfWork2.
CreateGenericRepository<SomeEntityTypeInAnotherModel>();
// Do some work
unitOfWork2.Commit();
}
}
}
var service = new MyService(new UnitOfWorkFactory());
请记住,艰苦的工作将在抽象存储库及其实现中进行。一旦您的服务类中不再有EF上下文,您就必须在repo接口中模拟许多方法,支持所有必要的场景来操作数据。我非常喜欢这种方式,但以这种方式在我的服务中实例化一个新的
UnitOfWork
或DatabaseFactory
,仍然需要引用实体框架,我正试图避免引用实体框架以分离关注点。我不希望我的服务依赖于EF,但我想我可能最终会打破这个规则。@Jisaak。我尝试了一个从EF中删除您的服务依赖性的建议。我认为这是可能的,但我已经稍微改变了您的设计,特别是将数据库工厂
替换为UnitOfWorkFactory
(接口和实现),请参见我的编辑…“我在IDatabaseFactory中处理单个扭曲的上下文”我感觉到了您的痛苦;我的很多代码似乎也存在时间和/或空间扭曲。
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);
}
// etc.
}
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>();
// Do some work
unitOfWork1.Commit();
}
using(var unitOfWork2 = _factory.Create("AnotherModelContainer"))
{
var repo2 = unitOfWork2.
CreateGenericRepository<SomeEntityTypeInAnotherModel>();
// Do some work
unitOfWork2.Commit();
}
}
}
var service = new MyService(new UnitOfWorkFactory());