Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework: ViewModel to Domain Model

I'm building an MVC 3 website. I have a model looking like this:

public class Survey
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public DateTime DateStart { get; set; }

    public DateTime DateEnd { get; set; }

    // Not in view
    public DateTime DateCreated { get; set; }

    // Not in view
    public DateTime DateModified { get; set; }
}

Based on this I also have a View Model to edit the survey information:

public class SurveyEditViewModel
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public DateTime DateStart { get; set; }

    public DateTime DateEnd { get; set; }
}

When the user finishes editing I would like to persist the changes. Here's my controller post action:

    [HttpPost]
    public ActionResult Edit(SurveyEditViewModel model)
    {
        // Map the view model to a domain model using AutoMapper
        Survey survey = Mapper.Map<SurveyEditViewModel, Survey>(model);

        // Update the changes
        _repository.Update(survey);

        // Return to the overview page
        return RedirectToAction("Index");
    }

In my repository (it's a generic one for now) I have the following code:

    public void Update(E entity)
    {
        using (ABCDataContext context = new ABCDataContext())
        {
            context.Entry(entity).State = System.Data.EntityState.Modified;
            context.SaveChanges();
        }
    }

When this executes I get the following error: "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."

I guess this was to be expected. Mapping from the view model to the model doesn't give me a complete Survey object.

I could modify my controller to look like this. And then it works:

[HttpPost]
public ActionResult Edit(SurveyEditViewModel model)
{

    // Map the model to a real survey
    survey = _repository.Find(model.Id);
    survey.Name = model.Name;
    survey.Description = model.Description;
    survey.DateStart = model.DateStart;
    survey.DateEnd = model.DateEnd;

    // Update the changes
    _repository.Update(survey);

    // Return to the overview page
    return RedirectToAction("Index");
}

But I was wondering if a better way is available?

like image 978
Aetherix Avatar asked Dec 16 '22 22:12

Aetherix


1 Answers

[HttpPost]
public ActionResult Edit(SurveyEditViewModel model)
{
    // Fetch the domain model to update
    var survey = _repository.Find(model.Id);

    // Map only the properties that are present in the view model
    // and keep the other domain properties intact
    Mapper.Map<SurveyEditViewModel, Survey>(model, survey);

    // Update the changes
    _repository.Update(survey);

    // Return to the overview page
    return RedirectToAction("Index");
}
like image 103
Darin Dimitrov Avatar answered Dec 30 '22 09:12

Darin Dimitrov