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

EF Core关联实体加载异常:空值与重复记录问题排查

关于EF Core关联实体加载的问题

我在使用EF Core时遇到关联实体加载问题:

  • 最初查询User时,关联的UserGovernments始终为空
  • 手动修改代码后,又出现UserGovernment记录重复的情况

原代码(UserGovernments为空)

public static User GetUser(int userID)
{
    _context.Users.Where(x => x.UserId == userID)
                  .FirstOrDefault();
}

修改后的代码(出现重复记录)

public static User GetUser(int userID)
{
    using (var _context = new SafetyContext())
    {
        // find lga for this user
        var user_govs = from o in _context.Users
                        join i in _context.UserGovernments                           
                               on o.UserId equals i.UserId
                        where o.UserId == userID
                        select new { o, i };
                            
        var user = _context.Users
                           .Where(x => x.UserId == userID)
                           .FirstOrDefault();

        foreach (var lga in user_govs)
        {
            user.UserGovernments.Add(new UserGovernment { UserId = userID, UserGovernmentId = lga.i.UserGovernmentId, LocalGovId = lga.i.LocalGovId, StateId = lga.i.StateId });
        }

        return user;
     }
 }

相关模型类

public class User
{
    public int UserId { get; set; }
    public string Name { get; set; }

    public string Email { get; set; }

    public UserAccess AccessLevel { get; set; }

    public ICollection<UserGovernment> UserGovernments { get; set; }
}

public class UserGovernment
{
    public int UserGovernmentId { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
    public int StateId { get; set; }
    public State State { get; set; }
    public int LocalGovId { get; set; }
    public LocalGov LocalGov { get; set; }
}

public class LocalGov
{
    public int LocalGovId { get; set; }
    public string Name { get; set; }        
    public string LgaPid { get; set; }
    public ICollection<UserGovernment> UserGovernments { get; set; }
}

上下文配置

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     modelBuilder.Entity<UserGovernment>()
                 .HasKey(bc => new {bc.UserGovernmentId});

     modelBuilder.Entity<UserGovernment>()
                 .HasOne(bc => bc.User)
                 .WithMany(b => b.UserGovernments)
                 .HasForeignKey(bc => bc.UserId);
        
     modelBuilder.Entity<UserGovernment>()
                 .HasOne(bc => bc.LocalGov)
                 .WithMany(c => c.UserGovernments)
                 .HasForeignKey(bc => bc.LocalGovId);
}

错误原因及解决方法

1. 原代码UserGovernments为空的原因

EF Core默认关闭延迟加载,直接查询User时,导航属性UserGovernments不会被自动填充,必须显式指定加载关联实体。

2. 修改后出现重复记录的原因

执行user_govs查询时,EF Core上下文已经跟踪了查询到的UserGovernment实体;后续手动创建新对象添加到集合时,若上下文通过延迟加载或跟踪机制自动加载了原有关联实体,就会导致重复。

正确的解决方式

使用Include方法显式加载关联实体,这是EF Core加载导航属性的标准做法:

public static User GetUser(int userID)
{
    using (var _context = new SafetyContext())
    {
        return _context.Users
                       .Include(u => u.UserGovernments) // 显式加载关联的UserGovernments
                       .Where(x => x.UserId == userID)
                       .FirstOrDefault();
    }
}

如果需要进一步加载UserGovernment关联的State或LocalGov,可使用ThenInclude:

return _context.Users
               .Include(u => u.UserGovernments)
                   .ThenInclude(ug => ug.State) // 加载UserGovernment关联的State
               .Include(u => u.UserGovernments)
                   .ThenInclude(ug => ug.LocalGov) // 加载UserGovernment关联的LocalGov
               .Where(x => x.UserId == userID)
               .FirstOrDefault();

另外,建议在实体构造函数中初始化集合属性,避免空引用异常:

public class User
{
    public User()
    {
        UserGovernments = new List<UserGovernment>();
    }

    // 其他属性...
    public ICollection<UserGovernment> UserGovernments { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:50:27