使用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)
正确使用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,它看起来很容易,但会产生太多的性能问题,因此不值得使用