【问题标题】:Use AutoMapper to map two VM to one Entity object使用 AutoMapper 将两个 VM 映射到一个 Entity 对象
【发布时间】:2015-10-29 10:20:06
【问题描述】:

我正在使用 AutoMapper 将许多实体模型映射到我在控制器和视图中使用的视图模型 (.Net MVC) DB中有很多关系,所以我们的VM有很多孩子(他们有孩子,等等)

public class InvoiceVMFull : VMBase
{
    public int Id { get; set; }

    public InvoiceType InvoiceType { get; set; }

    public string Reference { get; set; }

    //.... shortened code for readability
    // list all entity fields

    public List<string> InvoiceMainAddress { get; set; }

    public List<string> InvoiceDlvAddress { get; set; }
}

它工作得很好,但是很慢并且总是从数据库中加载所有关系,而我通常只需要一些数据......

因此,我创建了一些轻型 VM,我想将其用于我们的大部分页面。

public class InvoiceVMLite : VMBase
{
    public int Id { get; set; }

    public string Reference { get; set; }

    //.... shortened code for readability
    // list only some of the entity fields (most used)

    public StoredFileVM InvoiceFile { get; set; }
}

问题是我找不到方法:

  • 将一个实体对象映射到两个虚拟机,以及如何使用上下文(调用的页面或事件)选择正确的实体对象(从数据库加载)
  • 将两个 VM 映射到一个实体并仅保存(在 DB 上)使用的 VM 中存在的字段,而不删除不存在的字段

我尝试创建两个 VM 的映射:

Mapper.CreateMap<Invoice, InvoiceVMLite>();
Mapper.CreateMap<Invoice, InvoiceVMFull>();

但是当我尝试调用 Lite 的映射时,它不存在(已被 Full 覆盖):

Mapper.Map(invoice, InvoiceEntity, InvoiceVMLite)

【问题讨论】:

    标签: c# asp.net-mvc entity-framework automapper viewmodel


    【解决方案1】:

    正确使用地图功能

    您似乎错误地调用了 map。试试这些

    var vmLite = Mapper.Map<Invoice, InvoiceVMLite>(invoice);
    var vmFull = Mapper.Map<Invoice, InvoiceVMFull>(invoice);
    

    var vmLite = Mapper.Map(invoice);// would work if it were not ambiguous what the destination was based on the input.

    实体到两个视图模型

    您通常会创建两个映射,一个用于来自一个实体的每个视图模型。我建议最干净的方法是为每个视图模型设置两个单独的视图(控制器中的单独操作)。在您决定使用哪个上下文之后,这可能涉及快速重定向。

    查看模型到实体

    Automapper 不适用于从视图模型映射到实体,原因有很多,包括您面临的挑战。相反,您将传递特定的参数。 Automapper 的作者 Jimmy Bogard 写了good article 说明为什么会这样。

    【讨论】:

    • E->VM :我尝试为具有相同目的地的两个 VM 创建地图,但是当我调用 Mapper.Map 时出现错误:缺少地图配置。我认为第二个映射会覆盖第一个映射。我可以在没有性能或安全问题的情况下在 Action 中调用 createMap 吗?我可以为相同的类型多次调用它还是必须检查它是否已经映射? VM->E : 所以我别无选择,只能自己做?为VM找到好的实体,将所有链接字段一一设置,修改实体对象,然后发送到DB保存?如果是这样,我认为完全放弃 AutoMapper 会更容易。
    • E>VM 会有不同的目的地,每个 vm 都有一个目的地。听起来你的顺序可能是错误的
    • VM->E 完整阅读那篇文章。最好具体说明您要保存的内容。我发现 automapper 确实会随着您的模型增长而有所帮助,并且您可能会欣赏这一点,因为您的视图模型变化更大。也就是说,如果您不了解或不认同它背后的想法,那么它可能不适合您。
    • 对于 E-> VM,我尝试创建两个 VM 的映射: Mapper.CreateMap(); Mapper.CreateMap();但是当我尝试调用 Lite 的映射时,它不存在(已被 Full 覆盖):Mapper.Map(invoice, InvoiceEntity, InvoiceVMLite)
    • 现在会更新答案,刚刚看到你做错了什么
    【解决方案2】:

    我无法使用 AutoMapper 做到这一点,因此我创建了自己的转换方法(实体 VM),具有很多反射性,并在每个 VM 类中处理特定情况。

    现在我可以轻松地从实体获取完整或精简的虚拟机,并指定我想要的相关深度。所以它比 AutoMapper 更快,适应性更强

    我可以将虚拟机保存到我创建的或从基础获得的实体(如果需要,只保存修改的字段)。所以它比 AutoMapper 快很多且适应性强

    结论:不要使用 autoMapper,它看起来很简单,但会产生很多性能问题,不值得

    【讨论】:

      猜你喜欢
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      相关资源
      最近更新 更多