3

Is there any method to update an object from a strongly typed object without listing each field ?
Lets consider the following case:

    using (var context = new MyDBEntities())
{
     var user = (User)Session["EditedUser"];
     var oldUser = context.Users.FirstOrDefault(o => o.Id == user.Id);
     oldUser.FirstName= user.FirstName;
     oldUser.LastName = user.LastName;
     etc ....
     context.SaveChanges();
}

I have 29 more fields and I am not willing to write them down one by one every time. What I am looking for should be similar to this

using (var context = new MyDBEntities())
{
     var user = (User)Session["EditedUser"];
     var oldUser = context.Users.FirstOrDefault(o => o.Id == user.Id);
     oldUser=user;
     context.SaveChanges();
}

Which fails for sure because of the entity's primary key violation. What I would like to achieve here is to update all the fields except the primary key value.

James Dayeh
  • 516
  • 1
  • 5
  • 13
  • 1
    Have you tried to attach it? e.g. `db.Users.Attach(user); db.Entry(user).State = EntityState.Modified;` – Silvermind Dec 23 '13 at 10:28
  • The user is already in the database, I am trying to update his properties from another user object. Attach will not reference to the old user, It will be attached as a new user. – James Dayeh Dec 23 '13 at 10:35
  • 1
    `AddObject` would be a new user, not `Attach` if you set the `[Key]` column to the same value of the existing user. – Silvermind Dec 23 '13 at 11:14

2 Answers2

4

Used the Attach function thanks to 'Silvermind' Now my code looks like this

using (var context = new MyDBEntities())
{
    try
    {
        var user = (User)Session["EditedUser"];
        context.Users.Attach(user);
        context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
        context.SaveChanges();
        Session["EditedUser"] = null;
        return "ok";
    }
    catch (Exception ex)
    {
        return ex.Message;
    }
}
Silvermind
  • 5,791
  • 2
  • 24
  • 44
James Dayeh
  • 516
  • 1
  • 5
  • 13
2

I know the accepted answer is seven year old as of this post, so it is likely done a different way now. I found an alternative method that works from this source. One additional note that I found was that you have to then save the object. Here is a full code example in what worked for me. This turned out to be truly priceless as I have performed many work around methods in updating old/ new objects and this makes it a real one stop shop!

EDIT: Modified to match the much simpler format suggested by Gert Arnold

    [ResponseType(typeof(Order))]
    public IHttpActionResult PutOrder(Order ord)
    {
        if (!ModelState.IsValid)
        {
            return Content(HttpStatusCode.BadRequest, "Could not save order, invalid model.");
        }
        var current = db.Order.Find(ord.OrderId);
        try
        {              
            if (current != null)
            {
                // Update Order in Six Hat to match order in IB
                db.Entry(current).CurrentValues.SetValues(ord);
                db.SaveChanges();
                // TODO: Send Order Change Notifications
            }
        }
        catch(Exception e)
        {
            return Content(HttpStatusCode.BadRequest, e.Message);
        }

        return Ok(current);
    }
Anthony Griggs
  • 1,469
  • 2
  • 17
  • 39
  • 1
    Unfortunately, the redundant line `db.Entry(current).State = System.Data.Entity.EntityState.Modified;` throws away the advantages of `CurrentValues.SetValues`, which is a leaner update statement. See https://stackoverflow.com/a/30824229/861716. – Gert Arnold Sep 22 '20 at 19:45
  • 1
    @GertArnold Thank you for that... I just basically followed the model that was in the link. Appreciate the much better and simpler format of your method! – Anthony Griggs Sep 23 '20 at 18:21