c# - 将 ViewModel 投影回模型的最佳方式

标签 c# asp.net-mvc asp.net-mvc-4 mvvm automapper

考虑使用 ViewModel:

public class ViewModel
{
    public int id { get; set; }
    public int a { get; set; }
    public int b { get; set; }
}

和这样的原始模型:

public class Model
{
    public int id { get; set; }
    public int a { get; set; }
    public int b { get; set; }
    public int c { get; set; }
    public virtual Object d { get; set; }
}

每次获取 View 模型时,我都必须将所有 ViewModel 属性一一放入 Model 中。像这样的东西:

var model = Db.Models.Find(viewModel.Id);
model.a = viewModel.a;
model.b = viewModel.b;
Db.SaveChanges();

这总是会导致很多问题。我什至有时会忘记提及某些属性,然后灾难就发生了! 我在寻找类似的东西:

Mapper.Map(model, viewModel);

顺便说一句:我只使用 AutoMapper 将 Model 转换为 ViewModel,但反之亦然,我总是会遇到错误。

最佳答案

总的来说,这可能不是您正在寻找的答案,但这里引用了 AutoMapper 作者的话:

I can’t for the life of me understand why I’d want to dump a DTO straight back in to a model object.

我认为从 ViewModel 映射到 Entity 的最佳方法不是为此使用 AutoMapper。 AutoMapper 是一个很好的工具,用于映射对象而不使用除静态类以外的任何其他类。否则,代码会随着每个添加的服务变得越来越困惑,并且在某些时候您将无法跟踪导致您的字段更新、集合更新等的原因。

经常面临的具体问题:

  1. 需要非静态类来为您的实体进行映射

    您可能需要使用 DbContext 来加载和引用实体,您可能还需要其他类 - 一些将图像上传到文件存储的工具,一些对密码进行散列/加盐的非静态类,等等。 . 你要么必须以某种方式将它传递给 automapper,要么在 AutoMapper 配置文件中注入(inject)或创建,这两种做法都很麻烦。

  2. 可能需要在同一个 ViewModel(Dto) -> 实体对上进行多个映射

    对于相同的 View 模型实体对,您可能需要不同的映射,这取决于该实体是否是聚合,或者不是+基于您是否需要引用该实体或引用和更新。总的来说,这是可以解决的,但会在代码中产生很多不需要的噪音,而且更难维护。

  3. 非常脏的代码,很难维护。

    这是关于基元(字符串、整数等)的自动映射和手动映射引用、转换后的值等。自动映射器的代码看起来真的很奇怪,您必须为属性定义映射(或者不定义,如果您更喜欢隐式自动映射器映射——与 ORM 配对时也具有破坏性)并使用 AfterMap、BeforeMap、Conventions、ConstructUsing 等来映射其他属性,这使事情变得更加复杂。

  4. 复杂映射

    当您必须进行复杂的映射时,例如从 2 个以上的源类映射到 1 个目标类,您将不得不使事情变得更加复杂,可能调用如下代码:

    var target = new Target();
    Mapper.Map(source1, target);
    Mapper.Map(source2, target);
    //etc..
    

    该代码会导致错误,因为您不能将 source1 和 source2 映射在一起,并且映射可能取决于将源类映射到目标类的顺序。如果您忘记执行 1 个映射,或者如果您的映射在 1 个属性上有冲突的映射,我不是在说互相覆盖。

这些问题可能看起来很小,但在我面临使用自动映射库将 ViewModel/Dto 映射到实体的几个项目中,这比从未使用它造成的痛苦要大得多。

这里有一些链接:

关于c# - 将 ViewModel 投影回模型的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35959968/

相关文章:

c# - 如何在不在数据库中创建相应表的情况下创建实体集或模型 - Entity Framework

javascript - 在 MVC View 中使用 Knockout 多次生成并跟踪相同的模板?

c# - 如何通过 ASP NET MVC 表单发布传递对象实例

asp.net-mvc - 调用 SaveChanges() 时排除更新属性

c# - 能够使用 MS 机器人框架接收文件

c# - 我可以在 Xamarin.Forms 中以编程方式更改 styles.xml 吗?

c# - 更改属于另一个进程的窗口的大小和位置

c# - System.Configuration.ConnectionStringSettingsCollection.this[string].get 返回 null

asp.net-mvc-4 - HttpPost 在 asp.net mvc4 中不工作

asp.net-mvc-4 - ASP.NET MVC 中的时间输入字段