Entity Framework如何填充需关联查询的NotMapped属性?
优化PostInfo点赞数统计的几种高效方案
嘿,我懂你的痛点——手动循环赋值还得加载整个LikeInfo集合,确实不够高效。下面给你几个更优的解决方案,既能在数据库层面完成统计,又不用手动处理循环:
方案一:直接投影构造对象(最直接)
这种方式会让数据库只查询你需要的PostInfo字段和对应的点赞数,完全不会加载LikeInfo的具体数据,性能拉满:
var postsWithLikeCount = context.PostInfoes .Where(post => post.UserId == userId) .Select(post => new PostInfo { // 这里替换成你PostInfo实体的所有实际属性 Id = post.Id, UserId = post.UserId, Title = post.Title, Content = post.Content, CreateTime = post.CreateTime, // ... 其他属性 LikeCount = post.LikeInfoes.Count() }) .ToList();
优点:一步到位,数据库层面完成统计,内存开销极小。如果你的PostInfo属性不多,这个方案最省心。
方案二:分组统计+左连接(适配无点赞的帖子)
如果有些帖子可能没有任何点赞,用左连接可以确保LikeCount默认是0,避免出现null:
// 先统计每个帖子的点赞数 var postLikeStats = context.LikeInfoes .Where(like => like.PostInfo.UserId == userId) .GroupBy(like => like.PostId) .Select(group => new { PostId = group.Key, LikeCount = group.Count() }); // 关联PostInfo并填充LikeCount var posts = context.PostInfoes .Where(post => post.UserId == userId) .GroupJoin( postLikeStats, post => post.Id, stat => stat.PostId, (post, stats) => new PostInfo { Id = post.Id, UserId = post.UserId, Title = post.Title, // ... 其他属性 LikeCount = stats.FirstOrDefault()?.LikeCount ?? 0 }) .ToList();
优点:专门处理无点赞的帖子场景,统计逻辑更严谨。
方案三:用AutoMapper简化投影(适合属性多的情况)
如果你的PostInfo有很多属性,手动写投影太麻烦,可以用AutoMapper的ProjectTo来自动映射:
首先配置AutoMapper映射规则:
var config = new MapperConfiguration(cfg => { cfg.CreateMap<PostInfo, PostInfo>() .ForMember(dest => dest.LikeCount, opt => opt.MapFrom(src => src.LikeInfoes.Count())); }); var mapper = config.CreateMapper();
然后执行查询:
var posts = context.PostInfoes .Where(post => post.UserId == userId) .ProjectTo<PostInfo>(mapper.ConfigurationProvider) .ToList();
优点:不用手动维护所有属性的映射,代码更简洁,适合属性较多的实体类。
为什么你的原方案不够理想?
你原来用Include(x => x.LikeInfoes)会把该用户所有帖子的点赞记录全部加载到内存中,数据量大的时候会占用大量内存,之后的循环赋值也是额外的内存操作。上面的方案都是让数据库直接返回统计后的点赞数,避免了不必要的数据加载,性能提升非常明显。
内容的提问来源于stack exchange,提问作者Ali Yousefi
相关产品推荐
相关产品推荐

