我正在使用Automapper从EF Core 2实体投影到DTO。我的查询返回一个IEnumerable的DTO实例。我的DTO上的一个属性是IEnumerable,它通过源实体之间的多对多关系填充。下面列出的解决方案有效,但它会产生许多单独的SQL SELECT
查询。
有没有办法映射多对多,EF可以编译单SELECT
个查询而不是n
个查询?
TSource:
public class FilterList
{
public int Id { get; set; }
public ICollection<FilterListLanguage> FilterListLanguages { get; set; }
public string Name { get; set; }
public string ViewUrl { get; set; }
...
}
TDestination:
public class FilterListSummaryDto
{
public int Id { get; set; }
public IEnumerable<string> Languages { get; set; }
public string Name { get; set; }
public string ViewUrl { get; set; }
}
映射配置文件:
CreateMap<FilterList, FilterListSummaryDto>()
.ForMember(dto => dto.Languages,
conf => conf.MapFrom(list => list.FilterListLanguages.Select(x => x.Language.Name)));
查询:
public async Task<IEnumerable<FilterListSummaryDto>> GetAllSummariesAsync()
{
return await filterListsDbContext.FilterLists
.AsNoTracking()
.OrderBy(x => x.Name)
.ProjectTo<FilterListSummaryDto>()
.ToListAsync();
}
执行的SQL查询示例:
...
SELECT `x.Language`.`Name`
FROM `filterlists_languages` AS `x0`
INNER JOIN `languages` AS `x.Language` ON `x0`.`LanguageId` = `x.Language`.`Id`
WHERE @_outer_Id = `x0`.`FilterListId`
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (1ms) [Parameters=[@_outer_Id='82' (DbType = UInt16)], CommandType='Text', CommandTimeout='30']
SELECT `x.Language`.`Name`
FROM `filterlists_languages` AS `x0`
INNER JOIN `languages` AS `x.Language` ON `x0`.`LanguageId` = `x.Language`.`Id`
WHERE @_outer_Id = `x0`.`FilterListId`
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (1ms) [Parameters=[@_outer_Id='86' (DbType = UInt16)], CommandType='Text', CommandTimeout='30']
SELECT `x.Language`.`Name`
FROM `filterlists_languages` AS `x0`
INNER JOIN `languages` AS `x.Language` ON `x0`.`LanguageId` = `x.Language`.`Id`
WHERE @_outer_Id = `x0`.`FilterListId`
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@_outer_Id='85' (DbType = UInt16)], CommandType='Text', CommandTimeout='30']
...