Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
    }
like image 418
Dan Beaulieu Avatar asked May 06 '15 02:05

Dan Beaulieu


People also ask

How do I update an existing record in Entity Framework?

The steps to update an existing entity are quite simple. First retrieve an instance of the entity from the EntitySet<T> (in our case ObjectSet<Customer>), then edit the properties of the Entity and finally call SaveChanges() on the context.

Does Entity Framework use repository pattern?

The Entity Framework DbContext class is based on the Unit of Work and Repository patterns and can be used directly from your code, such as from an ASP.NET Core MVC controller. The Unit of Work and Repository patterns result in the simplest code, as in the CRUD catalog microservice in eShopOnContainers.

What is the benefit of repository pattern in Entity Framework?

Benefits of Repository PatternIt centralizes data logic or business logic and service logic. It gives a substitution point for the unit tests. Provides a flexible architecture. If you want to modify the data access logic or business access logic, you don't need to change the repository logic.


2 Answers

Ok, I figured this out. The reason why there isn't an Update method in new repository patterns (Entity Framework 6) is because there's no need for one. You simply fetch your record by id, make your changes and then commit/save.

For example, this is my edit POST method from my postController:

[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 looks like this:

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);
    } 
}
like image 170
Dan Beaulieu Avatar answered Sep 25 '22 12:09

Dan Beaulieu


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.

like image 37
Erik Philips Avatar answered Sep 26 '22 12:09

Erik Philips