[英]Abstract Entity Framework
我想在实体框架和应用程序的其余部分之间创建一个抽象层。 但是我在使用实体框架时遇到了一些问题。
基本上(我也没有向您展示我创建的所有接口层),我将应用程序划分为几个项目,如下所示:
就像我说的那样,我想创建我的数据存储对象(在我的情况下是Database
对象)的抽象,但是我想要一个适用于文件或WCF存储的解决方案,这样我的业务层对DAL一无所知实现。
这是我在DAL中所做的一瞥:
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain>
where TDbContext : DbContext, new()
where TEntity : class
where TDomain : class
{
protected TDbContext _context;
protected DbSet<TEntity> _dbSet;
public GenericDao(TDbContext dbContext)
{
this._context = dbContext;
this._dbSet = dbContext.Set<TEntity>();
}
public TDomain Create()
{
return this.ToDomain(this._dbSet.Create());
}
public IList<TDomain> GetAll()
{
return this._dbSet.ToList().Select(entity => this.ToDomain(entity)).ToList();
}
public void Update(TDomain domain)
{
var entity = this.ToEntity(domain);
var entry = this._context.Entry(entity);
entry.State = EntityState.Modified;
}
public void Remove(TDomain domain)
{
_dbSet.Remove(this.ToEntity(domain));
}
protected abstract TDomain ToDomain(TEntity entity);
protected abstract TEntity ToEntity(TDomain domain);
}
通过阅读代码,您可能会发现我的代码有什么问题:当我尝试删除或更新实体时,我没有在操纵连接到Entity Framework的实体。 如果我尝试将我的实体附加到dbContext
,它将失败,因为上下文中已经存在一个具有相同ID的实体。
我已经考虑过几种解决方案,但是没有一个能让我满意。
也许我的方法做错了什么? 我对存储库和DAO模式有些困惑(我读了任何东西,关于互联网上的区别却截然相反)。
您有两种选择:
为每个操作初始化新的dbcontext
,并在操作结束时将其处置:
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain> where TDbContext : DbContext, new() where TEntity : class where TDomain : class { protected Func<TDbContext> _contextFactory; public GenericDao(Func<TDbContext> contextFactory) { _contextFactory = contextFactory; } public TDomain Create() { using(var context = _contextFactory()) { return context.Set<TEntity>().Create(); } } public IList<TDomain> GetAll() { using(var context = _contextFactory()) { return context.Set<TEntity>().ToList() .Select(entity => this.ToDomain(entity)).ToList(); } } public void Update(TDomain domain) { using(var context = _contextFactory()) { var entity = this.ToEntity(domain); context.Attach(entity); var entry = this._context.Entry(entity); entry.State = EntityState.Modified; context.SaveChanges(); } } public void Remove(TDomain domain) { using(var context = _contextFactory()) { var entity = this.ToEntity(domain); context.Attach(entity); context.Set<TEntity>.Remove(entity); context.SaveChanges(); } } protected abstract TDomain ToDomain(TEntity entity); protected abstract TEntity ToEntity(TDomain domain); }
或者你可以尝试找到实体的实例dbcontext
使用属性Local
的DbSet
:
var contextEntity = context.Set<TEntity>().Local .Where(c=>c.Id == entity.Id).FirstOrDefault();
您似乎陷入了对抽象中的实现进行编码的过程。 如果将接口注入到泛型而不是具体类型(如EF),则GenericDao会变得更加灵活。 您可以注入任何选择的实现,只要它实现了所需的接口即可。 就您而言,是WCF,文件或其他。 例如;
protected IDbContext _context;
public GenericDao(IDbContext dbContext)
{
this._context = dbContext;
}
public void Remove(TDomain domain)
{
_context.Remove(this.ToEntity(domain));
}
//abstraction
public interface IDbContext
{
void Remove(Entity entity);
}
//EF Implementation
public MyEfClass : IDbContext
{
public void Remove(Entity entity)
{
//code to remove for EF example
context.Attach(entity);
context.State = EntityState.Modified;
context.Set<TEntity>.Remove(entity);
context.SaveChanges();
}
}
//WCF Implementation
public MyWCFClass : IDbContext
{
public void Remove(Entity entity)
{
//Wcf implementation here
}
}
//File example
public FileWriter : IDbContext
{
public void Remove(Entity entity)
{
LoadFile();
FindEntry(entity);
WriteFile(entity);
SaveFile();
}
public void LoadFile()
{
//use app settings for file directory
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.