Search code examples
c#asp.net-mvc-5entity-framework-6asp.net-identityrepository-pattern

Updating records using a Repository Pattern with Entity Framework 6


I'm writing a simple blog application and trying to establish CRUD operations in my generic repository pattern but I'm getting an error on my update method that says:

'System.Data.Entity.DbSet' does not contain a definition for 'Entry' and no extension method 'Entry' accepting a first argument of type 'System.Data.Entity.DbSet' could be found (are you missing a using directive or an assembly reference?)

I followed a post that explained how to 'fake' Entry() by adding additional level of indirection over DbContext. However in MVC 5 we're inheriting from: IdentityDbContext and not DbContext. I did try implementing the authors fix but the error persists.

My Question

How can I add an update method to my repository in Entity Framework 6 using IdentityDbContext? If we aren't supposed to do it this way then how do I update a record with this pattern?

I should note that all other the other methods work as expected.

My generic Repository:

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
    }

Solution

  • Update should look like (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 looks like this:

    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;
      }
    }
    

    You can view a full explaination to the answer for Efficient way of updating list of entities for more information on the details of just an update.