Ethan Pelton
Ethan Pelton

Reputation: 1796

Does every property of an entity need to be included in an update

I have an entity "Rep"...

public partial class rep
{
    public string repid { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Title { get; set; }
    public string Department { get; set; }
    many, many more properties...
}

I then have a form that updates only the rep's first and last name. When the form is submitted, the first and last name are updated, but every other property is set to null.

I want the other properties to be left alone so they retain there existing values.

I could include all of the properties of the entity with hidden form fields to pass their values along to the Edit method, but is there a better/easier way?

I'm familiar with setting the IsModified property...

entry.Property(e => e.Title).IsModified = true;

But that seems unnecessary as well. Is this the way to go, or is there a better way?

Upvotes: 0

Views: 191

Answers (3)

CodeCaster
CodeCaster

Reputation: 151586

The code you use to render the view and update the entity are quite relevant but missing, but I can guess what they look like:

@model ...rep

@using (Html.BeginForm()) {

    @Html.HiddenFor(m => m.repid )
    @Html.TextBoxFor(m => m.FirstName )
    @Html.TextBoxFor(m => m.LastName)

    <input type="submit" />
}

And in your controller:

[HttpPost]
public ActionResult Update(rep model)
{
    using (var context = new MyContext())
    {
        context.reps.Attach(model);
        context.SaveChanges();
    }

    return RTA(...);
}

This is attaching the entity that was posted, which is an entirely new object that is unknown to the context and its change tracker. By attaching an entity like that, you tell the context this is the new representation you want saved, i.e. with most properties set to null.

You can easily fix this by first retrieving the entity and then updating only the required properties:

[HttpPost]
public ActionResult Update(rep model)
{
    using (var context = new MyContext())
    {
        var entity = context.reps.Find(rep.repid);

        entity.FirstName = model.FirstName;
        entity.LastName = model.LastName;           

        context.SaveChanges();
    }

    return RTA(...);
}

But don't do this. See What is ViewModel in MVC? or ViewModel Best Practices or search the web or this site on "mvc viewmodel".

Mainly because your database entity contains columns you don't want displayed or updated (mass assignment) and because sooner or later you will want to use extra properties in your view (dropdown data, script variables, related entities) that you can't stick in your database entities.

Genarally you can say: don't use entity models for view models, especially not when they are posted back. So the viewmodel is the way to go:

public class RepresentativeViewModel
{
    public string RepID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }    
}

You then only have to alter your view's model declaration:

@model ...RepresentativeViewModel

And your controller just looks like the easiest solution:

[HttpPost]
public ActionResult Update(RepresentativeViewModel model)
{
    using (var context = new MyContext())
    {
        var entity = context.reps.Find(rep.RepID);

        entity.FirstName = model.FirstName;
        entity.LastName = model.LastName;           

        context.SaveChanges();
    }

    return RTA(...);
}

You can of course replace the entity.FirstName = model.FirstName; mapping code into some automated solution, for example using AutoMapper.

Upvotes: 2

KevDevMan
KevDevMan

Reputation: 818

You have two methods you could try

  1. Create a view model with only the properties you want to update.

  2. Store the values I the other properties in hidden fields they will not be returned null

Upvotes: 0

Honorable Chow
Honorable Chow

Reputation: 3153

You either use the IsModified property like you mentioned or you can create a view model that has the properties you want to change and use a mapper, like AutoMapper, to copy the values from the input to the entity. Typically I have a base class that has my modifiable data and a subclass that has the relationships and data I don't want to change like CreatedBy and stuff. Hidden fields is defnitely NOT the way to go.

Upvotes: 0

Related Questions