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

C# EF Core查询Restaurant实体属性丢失报空引用异常排查

为什么我的类实例没有加载对应的属性?

问题描述

我定义了名为Restaurant的实体类:

namespace Futures.Api.Data.Models
{
    public class Restaurant
    {
        public Restaurant()
        {
            Dishes = new HashSet<Dish>();
        }
    
        [Display(Name = "Restaurant Id")]
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int RestaurantId { get; set; } 
    
        [Display(Name = "Restaurant Name")]
        public string RestaurantName { get; set; } = null!;
    
        [Display(Name = "Category Name")]
        public string CategoryName { get; set; } = null!;
    
        [Display(Name = "Restaurant Address")]
        public string RestaurantAddress { get; set; } = null!;
    
        [Display(Name = "Zone Id")]
        public int? ZoneId { get; set; }
    
        public virtual FoodCategory CategoryNameNavigation { get; set; } = null!;
        public virtual Zone? Zone { get; set; }
        public virtual ICollection<Dish> Dishes { get; set; }
        public virtual Dish Dish { get; set; }
    }
}

在XUnit测试类中按如下代码初始化Restaurant对象:

Restaurant restaurant1 = new Restaurant
{
    RestaurantName = "Khana",
    RestaurantAddress = "Tokyo",
    CategoryName = "Indian",
    ZoneId = 2
};

调用按名称查询餐厅的方法时抛出空引用异常,测试方法代码如下:

[Fact]
public async Task GetRestaurantByName()
{
    Restaurant restaurant = await _repository.GetByName("Khana");

    Assert.Equal("Khana", restaurant.RestaurantName);
}

报错信息:System.NullReferenceException : Object reference not set to an instance of an object.
调试时发现返回的restaurant实例除CategoryNameNavigation外,看不到RestaurantName等其他属性,调试自动窗口(Autos)显示内容如下:

restaurant    CategoryNameNavigation = null   
  Futures.Api.Data.Models.Restaurant

   CategoryNameNavigation   null    

   Futures.Api.Data.Models.FoodCategory
   +        this
 

调试器运行截图
GetByName查询方法实现如下:

public async Task<Restaurant?> GetByName(string restaurantName)
{
    return await _context.Restaurants
        .Include(restaurantRecord => restaurantRecord.Dishes)
        .Include(restaurantRecord => restaurantRecord.Zone)
        .Include(restaurantRecord => restaurantRecord.CategoryNameNavigation)
        .SingleOrDefaultAsync(record => record.RestaurantName.ToLower().Contains(restaurantName.ToLower()));
}

问题原因与排查方案

核心问题不是属性加载丢失,是查询根本没有拿到有效数据,返回值为null,直接访问null对象的属性自然抛出空引用,调试器显示的残缺属性是null对象的异常展示,不是实例化后属性丢了。
按优先级排查以下点:

  • 测试数据没有持久化到数据库:你只是在代码里new了restaurant1对象,既没有把它添加到EF上下文(_context.Add(restaurant1)),也没有调用SaveChangesAsync()把数据写入测试用的Sqlite库,数据库里根本不存在名为"Khana"的餐厅记录,SingleOrDefaultAsync匹配不到数据直接返回null。
  • 确认测试上下文实例一致性:如果是用Sqlite做集成测试,要保证插入测试数据和执行查询用的是同一个上下文实例,或者已经正确把数据提交到共享的测试库,避免不同上下文实例导致数据不可见。
  • 补充断言前置校验:测试方法里先加Assert.NotNull(restaurant)再校验属性值,后续遇到同类问题可以第一时间定位是查询无结果,不会误以为是属性加载异常。
  • 额外映射问题提示:你实体里定义的public virtual Dish Dish { get; set; }导航属性没有配置对应外键,后续EF生成迁移或者查询关联数据时可能抛出映射错误,和本次空引用无关,可以后续处理。

内容的提问来源于stack exchange,提问作者gabegi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:24:40