使用AutoMapper将两个VM映射到一个Entity对象

时间:2015-10-29 10:20:06

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

我正在使用AutoMapper将很多实体模型映射到我在控制器和视图中使用的View Model(.Net MVC) 数据库中存在很多关系,所以我们的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; }
}

问题是我找不到:

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

我尝试创建VM的映射:

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

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

Mapper.Map(invoice, InvoiceEntity, InvoiceVMLite)

2 个答案:

答案 0 :(得分:0)

正确使用地图功能

看起来你正在错误地调用地图。试试这些

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的作者吉米·博加德(Jimmy Bogard)写了一篇关于为什么会这样的good article的文章。

答案 1 :(得分:0)

我无法通过AutoMapper实现这一目标,因此我创建了自己的转换方法(Entity&lt; =&gt; VM),具有很多反身性,并且在每个VM类中处理特定情况。

现在,我可以轻松地从实体中获取完整或精简的虚拟机,并指定我想要的深度。因此,它比AutoMapper

更快,更具适应性

我可以将VM保存到我创建的实体(只保存已修改的字段)或者我从基础获得的。因此它比AutoMapper

更快,更具适应性

总结:不要使用autoMapper,它看起来很容易,但会产生很多性能问题而且不值得它