英文:
AutoMapper: What is the difference between CreateMap and CreateProjection?
问题
我正在寻找有关AutoMapper中CreateMap/CreateProjection和ProjectTo/MapTo之间差异的解释。我刚刚开始使用这个库,很难理解在何时使用什么。我部分理解ProjectTo与LINQ有一些关联,可以用于整个集合?我希望在Blazor Server Side项目中使用这个库。
我还在研究这两个库,因为我正在使用EF Core:
- https://github.com/AutoMapper/AutoMapper.Collection
 - https://github.com/AutoMapper/AutoMapper.Collection.EFCore
 
但由于我对该库还很陌生,我认为最好先从基础开始。
英文:
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:
- https://github.com/AutoMapper/AutoMapper.Collection
 - https://github.com/AutoMapper/AutoMapper.Collection.EFCore
 
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 明确禁用了 Map。CreateMap 允许两者都使用。
所以,如果你只需要通过 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)。
阅读更多:
- IQueryable
和 IEnumerable 之间有什么区别?  - 定义 
CreateProjection和CreateMap
CreateProjection明确禁用Map。CreateMap允许两者都使用。 - 11.0 升级指南:
如果你不使用Map,只使用ProjectTo,你应该使用CreateProjection而不是CreateMap。这样,你将只使用ProjectTo支持的API子集,启动速度会更快。 - 12.0 升级指南
你也不能为同一映射/成员分别配置Map和ProjectTo。 - 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 =>
    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();
  }
}
> The .ProjectTo<OrderLineDTO>() 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:
- What is the difference between IQueryable<T> and IEnumerable<T>?
 - Defining both 
CreateProjectionandCreateMap
>CreateProjectionexplicitly disablesMap.CreateMapallows both. - 11.0 Upgrade Guide:
> If you don’t useMap, justProjectTo, you should useCreateProjectioninstead ofCreateMap. That way you’ll use only the API subset supported byProjectToand start-up should be faster. - 12.0 Upgrade Guide
> You also cannot have for the same map/member separate configurations forMapandProjectTo. - AutoMapper ConvertUsing is not called
 
答案2
得分: 2
短答案是通常更好使用 CreateMap。
CreateMap 定义了可以同时用于 MapTo 和 ProjectTo 的映射,而 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论