域模型到ViewModel并使用MVC3中的存储库模式和实体框架再次返回

时间:2012-03-28 00:02:12

标签: c# asp.net-mvc-3 viewmodel repository-pattern automapper

我在这里阅读了http://lostechies.com/jimmybogard/2009/09/18/the-case-for-two-way-mapping-in-automapper/关于你可能不应该试图解开扁平化对象的方法,但考虑到我如何使用Entity Framework的存储库,实体模型是预期的,而不是ViewModels 。

我开始想知道我是否应采取不同的方法,是否有人对这类事情有任何最佳做法?或者是时候开始使用ValueInjector Using AutoMapper to unflatten a 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 个答案:

答案 0 :(得分:3)

如果你遵循'自然'(非常主观)的流程就像这样

创建 模型

  

ViewModel - &gt;映射器 - &gt;域实体 - &gt;存储库 - &gt;映射器 - &gt;持久性实体

显示 更新视图模型

  

持久性实体 - &gt;映射器 - &gt;视图模型

在第一种情况下,您将dto处理到域实体(应用业务规则等),然后将其发送到存储库,并以特定方式保存(EF实体)

在第二种情况下,您要加载将用于更新域模型的视图模型(DTO)。而不是重新加载整个域实体,然后将其映射到DTO,而是直接从存储库中进行。

您可能会说这种情况不适用于您,因为您直接针对EF工作。嗯,这就是技巧,域模型!=持久性模型!=视图模型。它们各不相同,有不同的顾虑。

因此,通过适当的分离,您将始终拥有:视图模型 - &gt;地图 - &gt;域实体 - &gt;地图 - &gt;持久性实体和相反的方向:持久性实体 - &gt;地图 - &gt;查看模型