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

本文关键字:一个 对象 Entity 映射 两个 AutoMapper 使用 VM | 更新日期: 2023-09-27 18:19:54

我正在使用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; }
}

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

所以我创建了一些轻型虚拟机,我想在我们的大部分页面上使用它。

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加载)
  • 将两个虚拟机映射到一个实体,并只保存(在DB上)所用虚拟机中存在的字段,而不擦除不存在的字段

我试图创建映射两者VM:

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

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

Mapper.Map(invoice, InvoiceEntity, InvoiceVMLite)

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

正确使用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写了一篇很好的文章来解释为什么会出现这种情况。

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

现在,我可以很容易地从实体中获得完整或精简的VM,还可以指定我想要去的深度关系。所以它比AutoMapper 更快、适应性更强

我可以将虚拟机保存到我创建的或从base获得的实体中(如果我愿意,只保存修改过的字段)。所以它比AutoMapper 快得多,适应性强得多

总之:不要使用autoMapper,它看起来很容易,但会产生太多的性能问题,因此不值得使用