首页 > 解决方案 > 使用 entityFramework Automapper .Net Core 的嵌套映射

问题描述

这是我对 Entity Framework 的查询:

var transportlist = await _context.Set<Transport>()
       .Include(transport => transport.TransportState)
       .Select(transport =>
           new
           {
               Transport = _mapper.Map<TransportDto>(transport),
               TransportState = _mapper.Map<TransportStateForTransportDto>(transport.TransportState),
           }
        )
        .Take(limitNumber)
        .ToListAsync();

 return transportlist;

这是我的 TransportDto :

public class TransportDto
{
    public int TransportId { get; set; }
    public TransportStateForTransportDto TransportState { get; set; }
    public bool Locked { get; set; }
}

这是我的 TransportStateForTransportDto :

public class TransportStateForTransportDto
{
    public string Label { get; set; }
}

我想要这样的结果:

[
    {
        "transportId": 123456,
        "transportState" : {
            "Label": "Deleted"
        },
        "locked" : false
    }
]

但是,我有这个(这有点合乎逻辑......):

[
    {
        "transport": {
            "transportId": 123456,
            "transportState" : {
                "Label": "Deleted"
             },
             "locked" : false
        },
        "transportstate": {
            "Label": "Deleted"
        }           
    }
]

我想过这样做:

var transportlist = await _context.Set<Transport>()
       .Include(transport => transport.TransportState)
       .Select(transport =>
           new
           {
               _mapper.Map<TransportDto>(transport),
           }
        )
        .Take(limitNumber)
        .ToListAsync();

 return transportlist;

但是,如果我这样做,JSON 中的属性 transportstate 等于 NULL。

因此,我正在尝试进行嵌套映射,其中 Transport 也应该映射其对象属性。请注意,所有属性都具有完全相同的名称。

我写了一个用于映射的配置文件:

public class TransportsProfile : Profile
    {
        public TransportsProfile()
        {
            CreateMap<TransportState, TransportStateForTransportDto>();
            CreateMap<Transport, TransportDto>();
        }
    }

预先感谢您的帮助。

标签: entity-framework.net-coreautomapperdto

解决方案


如果您使用 Automapper 8 或更高版本,您应该利用ProjectTo而不是Map将实体转换为 DTO。

var transportlist = await _context.Set<Transport>()
    .ProjectTo<TransportDto>(_mapper.ConfigurationProvider)
    .Take(limitNumber)
    .ToListAsync();

编辑:上面有 _mapper.Configuration,看起来配置是由 ConfigurationProvider 提供的。

鉴于您的 TransportDTO 包含对相关 TransportState DTO 的引用,automapper 应该能够准确地告诉 EF 相关实体需要哪些字段以确保正确加载它们。问题Map在于,这实际上是针对加载的对象,而不是 EF 可能会变成 SQL 的表达式。

使用时,Take您还应该有一个 Order By 子句,以确保在超过该限制时返回的项目是可预测的。

与使用Select投影一样,无需预先加载任何相关细节或禁用延迟加载。如果您的 DTO 是纯粹的简单数据容器并且不包含对其中实体的引用,EF 将简单地编写一个查询来提取所需字段。


推荐阅读