使用带有实体框架 6 的存储库模式更新记录

Posted

技术标签:

【中文标题】使用带有实体框架 6 的存储库模式更新记录【英文标题】:Updating records using a Repository Pattern with Entity Framework 6 【发布时间】:2015-07-15 23:17:48 【问题描述】:

我正在编写一个简单的博客应用程序并尝试在我的通用存储库模式中建立 CRUD 操作,但我的更新方法出现错误:

'System.Data.Entity.DbSet' 不包含对 'Entry' 并且没有扩展方法 'Entry' 接受第一个参数 可以找到类型“System.Data.Entity.DbSet”(您是否缺少 使用指令还是程序集引用?)

我遵循post that explained 如何通过在 DbContext 上添加额外的间接级别来“伪造”Entry()。但是在 MVC 5 中,我们继承自:IdentityDbContext,而不是 DbContext。我确实尝试实施作者的修复,但错误仍然存​​在。

我的问题

如何使用 IdentityDbContext 在 Entity Framework 6 中向我的存储库添加更新方法?如果我们不应该这样做,那么如何使用这种模式更新记录?

我应该注意,所有其他方法都按预期工作。

我的通用存储库:

public class BlogEngineRepository<T> : IRepository<T> where T : class
    
        protected DbSet<T> DbSet;

        public BlogEngineRepository(DbContext dataContext)
        
            DbSet = dataContext.Set<T>();
        

        #region IRepository<T> Members

        public void Insert(T entity)
        
            DbSet.Add(entity);
        

        public void Delete(T entity)
        
            DbSet.Remove(entity);
        

        public void Update(T entity)
         

           DbSet.Entry(entity).State = System.Data.Entity.EntityState.Modified;

        

        public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
        
            return DbSet.Where(predicate);
        

        public IQueryable<T> GetAll()
        
            return DbSet;
        

        public T GetById(int id)
        
            return DbSet.Find(id);
        

        #endregion
    

【问题讨论】:

【参考方案1】:

好的,我想通了。在新的存储库模式(实体框架 6)中没有 Update 方法的原因是因为不需要一个。您只需通过 id 获取您的记录,进行更改,然后提交/保存。

例如,这是我的 postController 中的编辑 POST 方法:

[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Edit([Bind(Include = "Id,Title,IntroText,Body,Modified,Author")] Post post)

    using (UnitOfWork uwork = new UnitOfWork())
    
        Post edit = uwork.PostRepository.GetById(post.Id);
        edit.Title = post.Title;
        edit.IntroText = post.IntroText;
        edit.Body = post.Body;
        edit.Modified = DateTime.Now;

        uwork.Commit();

        return RedirectToAction("Index");
    

RepositoryPattern 如下所示:

public class BlogEngineRepository<T> : IRepository<T> where T : class

    protected DbSet<T> DbSet;

    public BlogEngineRepository(DbContext dataContext)
    
        DbSet = dataContext.Set<T>();
     

    public void Insert(T entity)
    
        DbSet.Add(entity);
    

    public void Delete(T entity)
    
        DbSet.Remove(entity); 
    

    public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
    
        return DbSet.Where(predicate);
    

    public IQueryable<T> GetAll()
    
        return DbSet;
    

    public T GetById(int id)
    
        return DbSet.Find(id);
     

【讨论】:

您的存储库仍然有一个更新方法。鉴于你的解释,我猜它不需要,不是吗? @Alisson 你是对的,这是一个粗心的复制和粘贴。 很好的例子,在实践中很糟糕。 With EF there is no need to hit the database (select) to update object back (update). 我在这里很困惑,因为在 Edit Post 方法中,我们已经收到了带有更新值的“Post”类型的对象。那么为什么我们需要调用 Post edit = uwork.PostRepository.GetById(post.Id);返回一个新对象,然后获取帖子属性并分配值?我们不能只使用我们收到的参数吗?还有如何更新只是调用 uwork.Commit();这里 ?如果这没问题,那么为什么我们需要获取值而不是调用 Commit();只要 ?这可能听起来很疯狂,但我很困惑【参考方案2】:

更新应该看起来像 (expanding on Dan Beaulieu's answer):

[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Edit([Bind(Include = "Id,Title,IntroText,Body,Modified,Author")] Post post)

    using (UnitOfWork uwork = new UnitOfWork())
    
        post.Modified = DateTime.Now;
        uwork.PostRepository.Update(post);

        uwork.Commit();

        return RedirectToAction("Index");
    

RepositoryPattern 如下所示:

public class BlogEngineRepository<T> : IRepository<T> where T : class

  public BlogEngineRepository(DbContext dataContext)
  
    DbSet = dataContext.Set<T>();
    Context = dataContext;
  

  public T Update(T entity)
  
     DbSet.Attach(entity);
     var entry = Context.Entry(entity);
     entry.State = System.Data.EntityState.Modified;
  

您可以查看Efficient way of updating list of entities 答案的完整说明,以获取有关更新细节的更多信息。

【讨论】:

感谢 Erik 的参与。我已经有一段时间没有真正评估过这种模式了,但是对于那些希望实现显式 Update 方法的人来说,这似乎是一个明显的胜利。 +1

以上是关于使用带有实体框架 6 的存储库模式更新记录的主要内容,如果未能解决你的问题,请参考以下文章

多对多实体框架和存储库模式插入/更新

实体框架:部分更新记录不起作用

DAL 中的实体框架存储库模式,如何实现更新功能?

使用带有实体框架的动态字段按子记录排序

具有存储库模式的实体框架 DAL、BLL

带有实体框架的 CRUD WEB API