4

I'm new at entity framework, I was using Nhibernate. In Nhibernate to update an object it's not necessary to pass the id, you just pass the entity and Nhibernate matches the id by itself and update the entity. In EF I'm using this approach:

        protected virtual bool UpdateEntity(TEntity entity, int id)
        {
          using (var ctx = new GenericContext())
          {
              var list = ctx.Set<TEntity>().ToList();
              ctx.Entry<TEntity>(ctx.Set<TEntity>  ().Find(id)).CurrentValues.SetValues(entity);
              return ctx.SaveChanges() > 0;
        }
       }

That needs the id to update the entity. Is this the best approach? Is there some way to update the entity just by passing the entity without first finding it?

j0zeft
  • 597
  • 2
  • 10
  • 29
Diego Unanue
  • 6,576
  • 8
  • 47
  • 67

2 Answers2

17

It depends if you have auto tracking enabled. By default it is, which means that any entity you retrieve will be stored in the DbContext you used to retrieve it, along with a copy of its original values.

Then if you edit this entity, when you call DbContext.SaveChanges(), EF will go through all your entities, and compare them with their original values, and if any has changed, it will execute an update statement.

So if you both retrieve the Entity, Edit it, and want to save it, all in the scope of the same context. All you have to do is call contxt.SaveChanged() and EF will work out that this entity has been updated. (As long as you have not disabled AutoTracking)

Borrowing from Eriks code:

var ctx = new SchoolDBEntities() 

var student = ctx.Students.Where(s => s.Name == "John Doe").First();    

student.Name = "Erik Blessman";

ctx.SaveChanges(); // Will update the  student

Otherwise if this entity is manually created and does not belong to any DbContexts you will need to

  1. Attach your Entity to a new(or your current) DbContext (this will be automatically done for you if you set EntityState.Modified )
  2. Tell DbContext this entity has been modified by
  • var entry = context.Entry(entity); // Gets the entry for entity inside context
  • entry.State = EntityState.Modified; // Tell Entity Framework this entity has been modified
  1. Optionally tell EF which properties on your entity have been modified
  2. Call SaveChanges()
Community
  • 1
  • 1
Michal Ciechan
  • 13,492
  • 11
  • 76
  • 118
  • Nice answer, thanks. Note on "Attaching your Entity to a `DbContext`", as you say you can Attach, but setting to Modified will Attach for you; [more info here](https://stackoverflow.com/q/30987806/1175496) – Nate Anderson May 31 '17 at 23:25
7

http://www.entityframeworktutorial.net/EntityFramework4.3/update-entity-using-dbcontext.aspx

    Student stud;
    //1. Get student from DB
    using (var ctx = new SchoolDBEntities())
    {
        stud = ctx.Students.Where(s => s.StudentName == "New Student1").FirstOrDefault<Student>();
    }

    //2. change student name in disconnected mode (out of ctx scope)
    if (stud != null)
    {
        stud.StudentName = "Updated Student1";
    }

    //save modified entity using new Context
    using (var dbCtx = new SchoolDBEntities())
    {
        //3. Mark entity as modified
        dbCtx.Entry(stud).State = System.Data.Entity.EntityState.Modified;     

        //4. call SaveChanges
        dbCtx.SaveChanges();
    }
Erik Blessman
  • 573
  • 3
  • 11
  • 1
    That's the same aprouch that i'm using, get the object from db and then modified it. And I don't get the 2nd step, are you saying that you have to indicate wich properties changed. I just want to pass the entity with the changes and then EF get the object using it's id, and modified it. Like hibernate does. Without explicity specifing the id. – Diego Unanue Mar 08 '15 at 22:44
  • This is connected mode scenario – Maulik Modi Jun 21 '21 at 04:53