Модель домена для ViewModel и обратно с использованием шаблона хранилища и Entity Framework в MVC3 - PullRequest
4 голосов
/ 28 марта 2012

Я прочитал здесь http://lostechies.com/jimmybogard/2009/09/18/the-case-for-two-way-mapping-in-automapper/ о том, что вам, вероятно, не следует пытаться распрямить сплющенный объект, но, учитывая то, как я использую хранилище с Entity Framework, ожидаются модели Entity, а не ViewModels.

Я начал задаваться вопросом, должен ли я придерживаться другого подхода, есть ли у кого-нибудь лучшие практики для такого рода вещей? или это просто время начать использовать ValueInjector Использование AutoMapper, чтобы расстегнуть DTO ? и не слишком ли беспокоиться о отображении RecipeCreateViewModel обратно в Recipe?

Ниже мой код, чтобы дать вам представление о том, что у меня есть на данный момент.

// Entities
public class Recipe {
    public int Id { get; set; }

    public string Name { get; set; }
    public Course Course { get; set; }
}

public class Course {
    public int Id { get; set; }
    public string Name { get; set; }
}

// View Model
public class RecipeCreateViewModel {
    // Recipe properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Course properties, as primitives via AutoMapper
    [Required]
    public int CourseId { get; set; }
    // Don't need CourseName in the viewmodel but it should probably be set in Recipe.Course.Name
    //public string CourseName { get; set; }

    // For a drop down list of courses
    public SelectList CourseList { get; set; }
}


// Part of my View
@model EatRateShare.WebUI.ViewModels.RecipeCreateViewModel
...
<div class="editor-label">
    Course
</div>
<div class="editor-field">
    @* The first param for DropDownListFor will make sure the relevant property is selected *@
    @Html.DropDownListFor(model => model.CourseId, Model.CourseList, "Choose...")
    @Html.ValidationMessageFor(model => model.CourseId)
</div>
...


// Controller actions

public ActionResult Create() {
    // map the Recipe to its View Model
    var recipeCreateViewModel = Mapper.Map<Recipe, RecipeCreateViewModel>(new Recipe());
    recipeCreateViewModel.CourseList = new SelectList(courseRepository.All, "Id", "Name");
    return View(recipeCreateViewModel);
}

[HttpPost]
public ActionResult Create(RecipeCreateViewModel recipe) {
    if (ModelState.IsValid) {
        // set the course name based on the id that was posted
            // not currently checking if the repository doesn't find anything.
    recipe.CourseName = courseRepository.Find(recipe.CourseId).Name;
            var recipeEntity = Mapper.Map<RecipeCreateViewModel, Recipe>(recipe);
        recipeRepository.InsertOrUpdate(recipeEntity);
        recipeRepository.Save();
        return RedirectToAction("Index");
    } else {
        recipe.CourseList = new SelectList(courseRepository.All, "Id", "Name");
        return View(recipe);
    }
}

1 Ответ

3 голосов
/ 28 марта 2012

Если вы следуете «естественному» (очень субъективному) потоку, это так:

К Создать Домен Модель

ViewModel -> Mapper -> Entity Entity -> Repository -> Mapper -> Persistence Entity

К Дисплей Обновление вида модели

Персистентная сущность -> Mapper -> ViewModel

В первой ситуации вы обрабатываете dto в объекте домена (применяете бизнес-правила и т. Д.), Затем отправляете его в хранилище, где оно сохраняется определенным образом (объекты EF)

Во второй ситуации вы хотите загрузить модель представления (DTO), которая будет использоваться для обновления модели домена. Вместо того, чтобы перезагружать всю сущность домена и затем отображать ее в DTO, вы делаете это прямо из хранилища.

Вы, вероятно, скажете, что эти случаи не относятся к вам, так как вы работаете непосредственно против EF. Ну, вот в чем и состоит хитрость, модель предметной области! = Модель постоянства! = Модель просмотра. Все они разные и имеют разные проблемы.

Таким образом, при правильном разделении у вас всегда будут: модель представления -> карта -> объект домена -> карта -> объект персистентности и в обратном направлении: объект персистентности -> карта -> модель просмотра

...