1

I have a form that updates an entity with about 10 fields, but this particular form was created to update only three of the fields. All examples I have seen so far, the SaveChanges() method was used when the whole data is submitted. Submitting partial data is causing my entity to replace all other fields to NULL. The solution I found was to add 7 hidden parameters on my View page, but I am pretty sure there is a more elegant way to do so. I am new to MVC4,any tutorial about this issue will be very helpful.Thanks

I tried this:

        tblEmployee CurrentEmployee = model.EmployeeToDisplay;


        try{
            var ChosenEmployee = emp.SpecifiEmployee(Id);//retrieve selected employee
            CurrentEmployee.IsNew = false;
            CurrentEmployee.StatusID = 1;
            ChosenEmployee.ShortId = CurrentEmployee.ShortId;
            db.Entry(ChosenEmployee).State = EntityState.Modified;
            db.SaveChanges();
        }

But I got an error: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

Avrum
  • 269
  • 2
  • 8
  • 16
  • 2
    http://stackoverflow.com/a/9821029/1043198 – Ant P Sep 17 '13 at 13:42
  • You are doing fine! If you don't do this you will be strugle with more complexity for nothing, for exemple, using a ViewModel and then Map it to your model. – Fals Sep 17 '13 at 13:43
  • Thanks Fals, I already noticed that any other method will add some extra code, exactly what I am trying to avoid – Avrum Sep 18 '13 at 04:52
  • The comment/question from Ant P is spot on as far as the basic method goes. You attach only a base entity and it magically knows what to update. – w0rd-driven Sep 18 '13 at 17:43
  • `An entity object cannot be referenced by multiple instances of IEntityChangeTracker.` this error comes because you do `db.Entry(ChosenEmployee).State = EntityState.Modified;`. The changes to `ChosenEmployee` already adds the entity to the list of changes – Ackdari Apr 23 '21 at 14:06

2 Answers2

4

You can create a view model with only the editable fields in that form.

Then when saving the changes, you will need to retrieve the entity from the database, map the fields from the view model to the retrieved entity and finally call SaveChanges.

So given the entity FooEntity, you can create a view model EditFooViewModel with only the properties to be edited:

public class FooEntity
{
    public int Id {get; set;}
    public string Field1 {get; set;}
    public string Field2 {get; set;}

    public string NonEditableField1 {get; set;}
    public string NonEditableField2 {get; set;}
}

public class EditFooViewModel
{
    public int Id {get; set;}
    public string Field1 {get; set;}
    public string Field2 {get; set;}
}

Then when the form is submitted, retrieve the entity and update it with the view model values before saving the changes. Keeping the example simple, a controller method following this idea may look like this:

public ActionResult SaveChanges(EditFooViewModel viewModel)
{
    ... check model state for errors...

    //Get the current entity value
    var entity = dbContext.FooEntities.Single(e => e.Id == viewModel.Id);

    //Map values from view model to entity
    entity.Field1 = viewModel.Field1;
    entity.Field2 = viewModel.Field2;

    //Save changes 
    dbContext.SaveChanges();

    ...
}

EDIT - When should I use view models?

View models will help you decoupling the controller/views from the business layer. This means the View models could provide a different view of your business objects (combining multiple entities in a single view model, reducing the exposed properties or taking care about formatting data!) and they will reduce the impact that changes on the business layer will have on the controller/views and vice-versa. (From simple changes like renaming a property in the backend to bigger ones like exposing the business layer as a rest json service)

They will also prevent you from exposing any unwanted properties as hidden fields, or manually setting the editable properties as modified (which is very similar to the mapping code following the view model pattern!). You also avoid exposing your entire business object if you have any actions returning your entities as json. Another benefit is that you prevent subtle bugs when you forget to manually attach and set modified properties in EF(or other backend you may be using)

It is true that they add some complexity of their own, mainly an additional set of classes (the view models) and the need for a view model-model mapping code.(Although there are tools that can help here, like Automapper)

Also take into account that for many applications, decoupling the controller/views from the backend will be a requirement. In those cases view models are the way to go.

I would also say that in my opinion, the extra code added when using view models is not too much compared with the alternatives:

  • You could decide using hidden fields for any additional field involved in a validation (so validations succeed) and then attach the model to the EF context, manually setting editable properties as modified. You don't need the view model class and the mapping code, and you also prevent an additional database hit for retrieving the current entity values before saving. However you need the hidden fields in the views, and code to set each editable property as modified in EF. Not to forget that if there is any new validation, you may need to add a new hidden field to your view.

  • Another option is not using hidden fields at all, and expose in the view only the editable fields from your entity. When saving, you will need to retrieve the entity from EF, manually map the editable fields and finally validate and save. This is pretty much the same as using view models, without a view model class. You still need to retrieve the entity from the backend and map the properties edited in the view before validate and save! While this may be enough in some scenarios, in others you will also need the benefits of using view models.

However this doesn't mean you should blindly use view models on every application. It is you who knows your concrete scenario and requirements, so you will need to consider the pros and contras of each alternative and decide which one makes the most sense!

Daniel J.G.
  • 34,266
  • 9
  • 112
  • 112
  • Absolutely right, ViewModels are a perfect solution for this purpose. I'd also add a plug for AutoMapper, which relieves you from having to map values over between your entity and ViewModel. – Mister Epic Sep 17 '13 at 14:26
  • @ChrisHardie absolutely agree with AutoMapper! I wouldn't also access the db in the controller, unless in very simple applications but I just wanted to keep the example simple. – Daniel J.G. Sep 17 '13 at 14:33
  • Thanks, but this solution will add some extra code, is there any advantage adding a viewmodel instead of just adding some hidden filelds? – Avrum Sep 18 '13 at 04:56
  • @user995159 I have added some comments regarding why/when using view models or another alternative. – Daniel J.G. Sep 18 '13 at 09:41
  • Daniel,sorry for the late response, thanks for the detailed answer, I will give a try now, using a viewmodel, so I will be able to compare the two solutions.I will let you know soon(and always mark it as answered).Thanks again – Avrum Sep 25 '13 at 18:26
  • @user995159, just consider the options available and pick up the one that makes the most sense to you and your requirements :) – Daniel J.G. Sep 27 '13 at 08:15
0

Is SaveChanges from EntityFramework?

Before calling saveChanges you could probably just retrieve your data, and update only the fields you want. It's hard to give an accurate example without seeing your controller or view of how you're getting/handling the data.

But I imagine it'd be something like this.

...
var myEntity = dbContext.MyEntities.Single(i=> i.Id);
//update only the fields you want updated
dbContext.SaveChanges();
Kyle Gobel
  • 5,530
  • 9
  • 45
  • 68
  • I have tried this before and did not help, I added the changed code on the body of my answer, please take a look. Thanks – Avrum Sep 18 '13 at 04:53