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