使用 entityFramework Automapper .Net Core 的嵌套映射

Nested mapping with 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 中的 属性 传输状态等于 NULL。

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

我写了一个映射配置文件,它是:

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

预先感谢您的帮助。

如果您使用的是 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 将简单地组成一个查询来提取所需的字段。