【问题标题】:How to update a domain object with ViewModel and AutoMapper using Entity framework?如何使用实体框架使用 ViewModel 和 AutoMapper 更新域对象?
【发布时间】:2011-07-27 20:05:12
【问题描述】:

如何使用 Entity 框架使用带有 AutoMapper 的 ViewModel 更新域对象?

我有一个可以编辑问题实体的视图。

这是我的编辑操作:

    public ActionResult Edit(int id)
{
    var question = db.Question.Single(q => q.question_id == id);

    Mapper.CreateMap<Question, EditQuestionViewModel>();
    EditQuestionViewModel eqvm = Mapper.Map<Question, EditQuestionViewModel>(question);

    eqvm.QuestionTypes = new SelectList(db.Question_Type, "type_code", "type_description", question.type_code);
    eqvm.Categories = new SelectList(db.Category, "category_id", "category_name", question.category_id);

    eqvm.Visibility = new SelectList(new Dictionary<int, string> {
        { 1, "Ja"},
        { 0, "Nej"}
    }, "Key", "Value");

    return View(eqvm);
}

我的 ViewModel 看起来像这样:

 public class EditQuestionViewModel
{
    public int question_id { get; set; }
    public string question_wording { get; set; }
    public bool visible { get; set; }
    public int question_number { get; set; }
    public string help_text { get; set; }
    public Category Category { get; set; }
    public Question_Type Question_Type { get; set; }

    public string SelectedCategory { get; set; }
    public string SelectedQuestionType { get; set; }
    public SelectList Categories { get; set; }
    public SelectList QuestionTypes { get; set; }
    public SelectList Visibility { get; set; }
    public string RefUrl { get; set; }

}

这是视图:

    @using (Html.BeginForm("Edit", "AdminQuestion", FormMethod.Post))
{
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Spørgsmål</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.question_wording, "Spørgsmål")
        </div>
        <div class="editor-field">
            @Html.TextAreaFor(model => model.question_wording, new { @class = "required", rows = 3, cols = 50 })
            @Html.ValidationMessageFor(model => model.question_wording)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.SelectedCategory, "Hvilken kategori tilhører dette spørgsmål?")
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.SelectedCategory, Model.Categories)
            @Html.ValidationMessageFor(model => model.SelectedCategory)
        </div>
        <div class="editor-label">
            @Html.LabelFor(x => x.SelectedQuestionType, "Spørgsmålstype")
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.SelectedQuestionType, Model.QuestionTypes)
            @Html.ValidationMessageFor(model => model.SelectedQuestionType)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.visible, "Skal dette spørgsmål være synligt?")
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.visible, Model.Visibility)
            @Html.ValidationMessageFor(model => model.visible)
        </div>

          <div class="editor-label">
            @Html.LabelFor(model => model.question_number, "Hvilket nummer har spørgsmålet inden for sin kategori?")
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.question_number, new { @class = "required digits" })
            @Html.ValidationMessageFor(model => model.question_number)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.help_text, "Hjælpetekst som hjælper brugeren med at forstå spørgsmålet:")
        </div>
        <div class="editor-field">
            @Html.TextAreaFor(model => model.help_text, new { rows = 20, cols = 50 })
            @Html.ValidationMessageFor(model => model.help_text)
        </div>
        <br />
        <input type="submit" value="Gem" />

    </fieldset>

提交表单时如何更新实体? ViewModel 和 EF Model 之间的映射应该如何使用 AutoMapper?

属性

public string SelectedCategory { get; set; }
public string SelectedQuestionType { get; set; }

ViewModel中应该与EF模型中的category_id和type_code链接

还要注意属性

public bool visible { get; set; }

我在我的数据库中使用 BIT。这是否适用于 SelectList 中使用的值 0 和 1?

谢谢!

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework-4


    【解决方案1】:

    你需要从实体框架中获取对象,然后像这样使用自动映射器:

    var item = repository.getbyid(model.Id);
    _mappingEngine.Map(viewModel, item);
    repository.save(item);
    

    【讨论】:

    • 谢谢! :) 我发现我必须使用 repository.SaveChanges();与 EF。另外,我必须先执行 _mapEngine.CreateMap() 才能使用 _mappEnginge.Map(); - 如果您可以更准确地编辑您的答案,我可以将其标记为已回答!
    • 存储库实现都是不同的,因此存储库的实际类型不应该真正考虑在内。关键是您应该如何获取实体引用,您不能只是从映射器中新建一个实体。 createmap 调用实际上不应发生在您需要它的代码中,而是发生在您使用引导程序或更直接的方式在 global.asax 中启动的自动映射器配置文件中。似乎您的问题与实体框架无关,我该如何使用 automapper。
    • 这是正确的做法。但是,Automapper 似乎在处理 EF 代理时存在问题,因此如果您使用具有延迟加载的 POCO,请注意这一点。
    【解决方案2】:

    当您提交表单时,您需要在控制器上执行一个操作来处​​理发送到服务器的帖子。

    因此,除了您当前拥有的编辑操作之外,您还需要定义另一个操作,如下所示:

    [HttpPost]
    public ActionResult Edit(EditQuestionViewModel model)
    {
        //Do the mapping to from your ViewModel to the EF model here
    
        return View();
    }
    

    它的作用是设置一个处理程序,以便您的表单可以将数据发送回控制器,并将表单上的字段绑定到模型参数。

    完成此操作后,您可以简单地将模型映射回 EF 并将其持久化到数据库中。

    此外,使用 bool 是完全有效的,EF 会为您翻译并将其作为 0 或 1 保存在数据库中。

    【讨论】:

    • 抱歉,我的问题不够清楚。从我的 ViewModel 到 EF 模型的映射应该是什么样子?假设我使用 AutoMapper
    • 使用 AutoMapper 从您的 VM 映射回您的 DM 是危险的,因为它可能会尝试设置比您想要的更多的值,这可能会导致意外结果。
    • @lomaxx,automapper 只会映射您告诉它的内容。如果您使用基本的 CreateMap() 而不告诉它如何映射,它将尝试匹配字段名称。您几乎应该始终准确定义地图的工作方式。
    • @nathan:这是真的,但它总是会尝试映射这些属性,所以如果你只需要小心你如何使用它。
    • @lomaxx,这就是配置文件的用途。如果您想在不同的上下文中以不同的方式映射同一个对象,请注入具有不同配置文件集的映射引擎。
    猜你喜欢
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多