AutoMapper: “CreateMap”和”CreateProjection”之间的区别是什么?

huangapple go评论57阅读模式
英文:

AutoMapper: What is the difference between CreateMap and CreateProjection?

问题

我正在寻找有关AutoMapper中CreateMap/CreateProjection和ProjectTo/MapTo之间差异的解释。我刚刚开始使用这个库,很难理解在何时使用什么。我部分理解ProjectTo与LINQ有一些关联,可以用于整个集合?我希望在Blazor Server Side项目中使用这个库。

我还在研究这两个库,因为我正在使用EF Core:

但由于我对该库还很陌生,我认为最好先从基础开始。

英文:

I am looking for an explanation of the difference between CreateMap/CreateProjection in automapper and ProjectTo/MapTo by relation.
I just got started with the library and I am having trouble understanding what to use when. I partially understand that ProjectTo has some relation to LINQ and can be used for entire collections? I wish to use this library in a Blazor Server Side project.

I am also looking into these two libraries as I am using EF Core:

But as I am new to the library I think it is a good idea to start with the base first before moving on.

答案1

得分: 8

以下是翻译好的内容:

TL;DR

如果你不使用 Map,而是使用 ProjectTo,你应该使用 CreateProjection 而不是 CreateMap。这样,你将只使用 ProjectTo 支持的 API 子集,并且启动速度会更快。

CreateProjection 明确禁用了 MapCreateMap 允许两者都使用。

所以,如果你只需要通过 ORM(如Entity Framework)进行实体到DTO的映射,然后使用 ProjectTo,那么请使用 CreateProjection,否则请使用 CreateMap

Details

文档中所述,如果你正在使用基于 IQueryable 的ORM,你可以使用 ProjectTo,这样AutoMapper+ORM组合可以生成适当的SQL语句,而不是将整个实体加载到内存中(如果你不是一对一地进行映射,这对性能可能有积极的影响),然后在客户端进行映射:

var configuration = new MapperConfiguration(cfg =>
    cfg.CreateProjection<OrderLine, OrderLineDTO>()
    .ForMember(dto => dto.Item, conf => conf.MapFrom(ol => ol.Item.Name)));

public List<OrderLineDTO> GetLinesForOrder(int orderId)
{
  using (var context = new orderEntities())
  {
    return context.OrderLines.Where(ol => ol.OrderId == orderId)
             .ProjectTo<OrderLineDTO>(configuration).ToList();
  }
}

.ProjectTo<OrderLineDTO>() 将告诉AutoMapper的映射引擎向 IQueryable 发出一个select子句,该子句将通知Entity Framework只需要查询Item表的Name列,就像你手动将你的 IQueryable 投影到一个带有 Select 子句的 OrderLineDTO 一样。

由于 ProjectTo 的性质,它在实际映射/操作方面要受到更多限制(并非所有内容都可以转化为SQL)。

阅读更多:

  1. IQueryable 和 IEnumerable 之间有什么区别?
  2. 定义 CreateProjectionCreateMap
    CreateProjection 明确禁用 MapCreateMap 允许两者都使用。
  3. 11.0 升级指南:
    如果你不使用 Map,只使用 ProjectTo,你应该使用 CreateProjection 而不是 CreateMap。这样,你将只使用 ProjectTo 支持的API子集,启动速度会更快。
  4. 12.0 升级指南
    你也不能为同一映射/成员分别配置 MapProjectTo
  5. AutoMapper ConvertUsing 未被调用
英文:

TL;DR

> If you don’t use Map, just ProjectTo, you should use CreateProjection instead of CreateMap. That way you’ll use only the API subset supported by ProjectTo and start-up should be faster.

> CreateProjection explicitly disables Map. CreateMap allows both.

So if you need only entity -> DTO mapping via ORM (like Entity Framework) and ProjectTo then use CreateProjection, otherwise use CreateMap.

Details

As written in the docs if you are working with ORM based on IQueryable you can use ProjectTo so the AutoMapper+ORM pair can generate a proper SQL statement instead of fetching the whole entity into memory (if your are not mapping in one-to-one fashion this can have positive effect on performance) and mapping it client side:

var configuration = new MapperConfiguration(cfg =&gt;
    cfg.CreateProjection&lt;OrderLine, OrderLineDTO&gt;()
    .ForMember(dto =&gt; dto.Item, conf =&gt; conf.MapFrom(ol =&gt; ol.Item.Name)));

public List&lt;OrderLineDTO&gt; GetLinesForOrder(int orderId)
{
  using (var context = new orderEntities())
  {
    return context.OrderLines.Where(ol =&gt; ol.OrderId == orderId)
             .ProjectTo&lt;OrderLineDTO&gt;(configuration).ToList();
  }
}

> The .ProjectTo&lt;OrderLineDTO&gt;() will tell AutoMapper’s mapping engine to emit a select clause to the IQueryable that will inform entity framework that it only needs to query the Name column of the Item table, same as if you manually projected your IQueryable to an OrderLineDTO with a Select clause.

Due to the nature of the ProjectTo it is much more limited in what it can actually map/do (not everything can be turned into SQL).

Read more:

  1. What is the difference between IQueryable<T> and IEnumerable<T>?
  2. Defining both CreateProjection and CreateMap
    > CreateProjection explicitly disables Map. CreateMap allows both.
  3. 11.0 Upgrade Guide:
    > If you don’t use Map, just ProjectTo, you should use CreateProjection instead of CreateMap. That way you’ll use only the API subset supported by ProjectTo and start-up should be faster.
  4. 12.0 Upgrade Guide
    > You also cannot have for the same map/member separate configurations for Map and ProjectTo.
  5. AutoMapper ConvertUsing is not called

答案2

得分: 2

短答案是通常更好使用 CreateMap

CreateMap 定义了可以同时用于 MapToProjectTo 的映射,而 CreateProjection 定义了只能与 ProjectTo 一起使用的映射,实际上禁用了 MapTo 的使用。

使用 CreateMap 将使您能够直接将内存对象和数据库查询(适用于 IQueryable 的查询)映射到您选择的对象中。

CreateProjection 可以在仅从数据库查询中进行映射时使用。

英文:

The short answer is it's generally better to use CreateMap.

Create map defines mappings that can be used for both MapTo and ProjectTo whereas CreateProjection defines mappings that only works with ProjectTo and effectively disables the use of MapTo.

Using CreateMap will give you the freedom to map in-memory objects and database queries (that work with IQueryable) directly into your chosen object.

CreateProjection can be used if you will only be mapping straight from DB queries

huangapple
  • 本文由 发表于 2023年2月16日 17:43:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470401.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定