如何将含嵌套ICollection的对象映射为MainDto列表?
问题分析与解决方案
你之前的代码存在几个明显错误,导致返回空集合:
- 转换器里的
o.One.Comments是错误写法,应该直接用o.Comments(o本身就是One的实例) tmp类未定义Name属性,但你在转换器里给Name赋值,会导致编译错误- 如果使用EF,若未通过
Include加载Comments和Likes导航属性,查询到的One实例中这些集合会是空的
以下是几种可行的实现方式:
方式一:直接映射One到MainDto列表(无需中间类)
直接在AutoMapper配置中定义One到IList<MainDto>的映射,跳过中间类:
profile.CreateMap<One, IList<MainDto>>() .ConvertUsing(one => one.Comments? .SelectMany(two => two.Likes? .Select(three => new MainDto { Name = one.Name, Text = two.Text, EmojiName = three.EmojiName })) .ToList() ?? new List<MainDto>());
使用时需确保EF查询时加载导航属性:
var one = dbContext.Ones .Include(o => o.Comments) .ThenInclude(c => c.Likes) .FirstOrDefault(o => o.Id == targetId); var mainDtoList = mapper.Map<IList<MainDto>>(one);
方式二:修正中间类tmp的实现
如果坚持使用中间类,先修正tmp的定义和转换器:
- 修正
tmp类,添加Name属性:
class tmp { public string Name { get; set; } public string Text { get; set; } public string EmojiName { get; set; } }
- 修正AutoMapper配置:
// 配置One到tmp列表的映射 profile.CreateMap<One, IList<tmp>>() .ConvertUsing(one => one.Comments? .SelectMany(two => two.Likes? .Select(three => new tmp { Name = one.Name, Text = two.Text, EmojiName = three.EmojiName })) .ToList() ?? new List<tmp>()); // 配置tmp到MainDto的映射 profile.CreateMap<tmp, MainDto>();
- 使用时先转tmp列表再转MainDto列表:
var tmpList = mapper.Map<IList<tmp>>(one); var mainDtoList = mapper.Map<IList<MainDto>>(tmpList);
方式三:使用EF直接投影(性能更优)
如果是从EF查询直接生成MainDto列表,可跳过AutoMapper转换器,直接用LINQ投影:
var mainDtoList = dbContext.Ones .Where(o => o.Id == targetId) .SelectMany(o => o.Comments) .SelectMany(c => c.Likes.Select(l => new MainDto { Name = o.Name, Text = c.Text, EmojiName = l.EmojiName })) .ToList();
内容的提问来源于stack exchange,提问作者TommySd
相关产品推荐
相关产品推荐

