EF Core使用Include加载Reviews数据异常,查询用户是否已评价产品时报错
问题根因
你的代码存在3个核心错误,是触发报错的直接原因:
Product实体的Reviews属性没有初始化默认值,即便用Include加载,如果该产品没有任何评价,这个集合会是null而非空集合,遍历时直接触发空引用报错- 查询
Product时仅Include了Reviews导航属性,没有IncludeReview下的Author导航属性,EF Core默认不会自动加载嵌套关联数据,导致访问x.Author.UserName时Author为null - 校验逻辑存在缺陷:
FirstOrDefault如果没找到匹配的评价会返回null,你直接访问返回值的.Author.UserName必然触发空引用异常
修复方案
1. 补全Product实体的集合初始化
给Reviews和Photos属性都加上默认空集合的初始化,避免无数据时集合为null:
// 修改Product实体定义中的集合属性 public ICollection<Review> Reviews { get; set; } = new List<Review>(); public ICollection<ProductPhoto> Photos { get; set; } = new List<ProductPhoto>();
2. 修改查询逻辑,嵌套加载关联的Author属性
查询Product的时候用ThenInclude加载Review下的Author:
var product = await _context.Products .Include(r => r.Reviews) .ThenInclude(r => r.Author) // 新增这行加载评价的作者信息 .FirstOrDefaultAsync(x => x.Id == request.ProductId);
3. 修正校验逻辑,避免空引用
不要直接访问FirstOrDefault返回值的属性,改用Any方法判断是否存在匹配评价,代码更简洁也不会有空引用问题:
// 替换原有的wasReviewed判断逻辑 if (product.Reviews.Any(x => x.Author.UserName == user.UserName)) { // 该用户已经提交过评价,直接返回 return null; }
可选优化:更高性能的校验方式
不需要把整个产品的所有评价都加载到内存再判断,直接通过数据库查询判断是否存在,性能更好,也不需要处理关联加载的问题:
// 不需要先查Product再遍历评价,直接查Review表判断 var hasReviewed = await _context.Reviews .AnyAsync(r => r.ProductId == request.ProductId && r.Author.UserName == _userAccessor.GetUsername()); if (hasReviewed) { return null; }
内容的提问来源于stack exchange,提问作者Ozure
相关产品推荐
相关产品推荐

