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

EF Core访问关联表时Colleague的StaffPosition导航属性为空问题

EF Core 关联表访问空引用异常问题

我尝试在EF Core中访问关联表,以便在View中展示对应列。我认为是遗漏了某个基础知识点,但始终无法解决问题。

简化后的场景:我有3个模型Branch、Colleague、StaffPosition,每个Colleague关联1个Branch,且仅可拥有1个StaffPosition,所有模型均使用Code First创建:

Branch 模型

public class Branch
{
    [Display(Name ="Branch ID")]
    public int BranchNumber { get; set; }
    [Display(Name ="Branch Name")]
    public string BranchName { get; set; }
    [Display(Name ="Contractor Code")]
    public int ContractorCode { get; set; }
    [Display(Name ="Addresss")]
    public string AddressOne { get; set; }
    // 为简化内容省略其余代码

    public ICollection<BranchHour> BranchHours { get; set; }
    public ICollection<Colleague> Colleagues { get; set; }
}

Colleague 模型

public class Colleague
{
    [Display(Name ="ID")]
    public int ColleagueID { get; set; }

    public int BranchID { get; set; }

    public int StaffPositionID { get; set; }

    [Display(Name ="Payroll Number")]
    public string PayrollNumber { get; set; }
    // 为简化内容省略其余代码
    
    public ICollection<Shift> Shifts { get; set; }
    [ForeignKey("StaffPositionID")]
    public StaffPosition StaffPosition { get; set; }
    [ForeignKey("BranchID")]
    public Branch Branch { get; set; }
}

StaffPosition 模型

public class StaffPosition
{
    public int StaffPositionID { get; set; }
    public string PositionName { get; set; }
    public ICollection<Colleague> Colleagues { get; set; }
}

视图模型定义

public class BranchShiftData
{
    public IEnumerable<Branch> Branches { get; set; }
    public IEnumerable<Colleague> Colleagues { get; set; }
    public IEnumerable<Shift> Shifts { get; set; }             
    public IEnumerable<StaffPosition> StaffPos { get; set; }
}

最初我没有在视图模型中加入Shifts和StaffPosition,但发现无法通过Colleague访问Shifts数据,因此补充了这两个属性。

页面后台OnGet方法代码

BranchData = new BranchShiftData();
BranchData.Branches = await _context.Branches
.Include(i => i.Colleagues)                        
.OrderBy(i => i.BranchNumber)
.ToListAsync();

if (id != null)
{
    BranchID = id.Value;
    Branch branch = BranchData.Branches
        .Where(i => i.ContractorCode == id.Value).Single();
    BranchData.Colleagues = branch.Colleagues
    .OrderBy(i => i.FullName);
}

if (colleagueID != null)
{
    ColleagueID = colleagueID.Value;                
    var selectedColleague = BranchData.Colleagues
        .Where(x => x.ColleagueID == colleagueID).Single();
   
    FullName = selectedColleague.FullName;
    PayrollNumber = selectedColleague.PayrollNumber;
    BranchName = selectedColleague.Branch.BranchName;
    ContractHours = selectedColleague.ContractHours;
    PositionName = selectedColleague.StaffPosition.PositionName;

我遇到的问题是:可以通过selectedColleague的关联属性获取BranchName,但无法用同样方式访问StaffPosition表的内容。在Web应用中选中单个Colleague时,程序会在为PositionName赋值的行抛出如下错误:

NullReferenceException: Object reference not set to an instance of an object.

经排查变量栈可知,selectedColleague的StaffPosition属性为null。
我无法理解的是:selectedColleague的BranchID为5558(取值正确),对应的Branch对象也已正确加载、可查看5558号Branch的所有信息;但selectedColleague的StaffPositionID取值正确为1,对应的StaffPosition属性却为空。
我的核心问题是:为什么可以通过selectedColleague.Branch.BranchName获取分支名称,却无法通过selectedColleague.StaffPosition.PositionName获取职位名称?


问题解答

原因分析

你在查询Branch时只通过Include预先加载了Colleagues关联集合,但没有继续加载Colleagues下的StaffPosition导航属性,EF Core默认不会自动加载未显式指定的关联属性,因此StaffPosition属性为null,访问时就会抛出空引用异常。
而Branch属性可以正常访问的原因是:你查询的根对象就是Branch,所有关联的Colleague对应的Branch对象已经被EF Core上下文追踪,所以自动填充了反向导航属性的值。

解决方法

修改你查询Branch的代码,使用ThenInclude方法继续加载Colleague下的StaffPosition导航属性即可:

BranchData.Branches = await _context.Branches
    .Include(i => i.Colleagues)
        .ThenInclude(c => c.StaffPosition) // 新增此行加载Colleague关联的StaffPosition
    // 如果后续需要访问Colleague的Shifts属性,可再加一行ThenInclude
    // .ThenInclude(c => c.Shifts)
    .OrderBy(i => i.BranchNumber)
    .ToListAsync();

问题解决后更新

所有遇到同类问题的开发者可参考上述解决方案。如果想要深入了解ThenInclude方法,可以自行查询EF Core官方相关文档;微软官方文档中也有对应教程,可自行查找针对Razor Pages的相关教程,也可找到对应MVC版本的教程。

内容的提问来源于stack exchange,提问作者Colin-G-Davidson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:27:02