You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 05:06:04