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

使用InMemory数据库时嵌套对象提交后丢失的原因及解决方法

问题:EF Core InMemory数据库中嵌套对象丢失的原因及解决办法

问题重现代码

实体类定义

public class Account { 
    public int id {get; set;}
    public string Name {get; set;} 
    public AccountEntry Entry {get; set;} 
}

public class AccountEntry { 
   public int id {get; set;}
   public DateTime date {get; set;} // 注:原代码中date应为DateTime,C#无原生date类型
   public string description {get; set;}
   public decimal hour {get; set;}
}

DbContext配置

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
    options.UseInMemoryDatabase("AccountDB");
}

添加记录方法

public void AddTimesheet(Account account)
{
     _context.Accounts.Add(account); // 注:原代码Accouunts为拼写错误,修正为Accounts
     _context.SaveChanges();
}

查询记录方法

public IList<Account> GetAllAccounts()
{    
    return _context.Accounts.ToList();
}

问题现象

第一次提交数据后,同一次请求中能正常查询到包含AccountEntry的完整记录;但提交新数据后,再次查询时,所有旧记录的Account.Entry都变为null,而Name等实体自身属性仍正常保留。


原因分析

  1. 导航属性默认不自动加载:EF Core(包括InMemory数据库)默认不会自动加载导航属性(即嵌套的AccountEntry)。第一次请求中,上下文还在跟踪刚添加的实体,导航属性会被上下文临时保留;但当使用新的上下文实例(比如新请求)查询时,默认只会查询Account表的自身字段,不会自动关联查询AccountEntry。
  2. 实体关联关系未明确配置:当前实体类没有定义外键字段,EF Core无法自动识别Account和AccountEntry的关联关系,导致InMemory数据库无法正确维护两者的关联,新增数据后旧关联丢失。

解决办法

方法1:查询时显式加载导航属性

修改查询方法,使用Include方法指定要加载的导航属性,确保查询时同时获取AccountEntry数据:

using Microsoft.EntityFrameworkCore; // 需要引入此命名空间

public IList<Account> GetAllAccounts()
{    
    return _context.Accounts.Include(a => a.Entry).ToList();
}

方法2:明确配置实体关联关系

在DbContext的OnModelCreating方法中配置Account和AccountEntry的关联关系,同时补充外键字段,让EF Core能正确识别并维护关联:

第一步:修改实体类,添加外键

public class Account { 
    public int id {get; set;}
    public string Name {get; set;} 
    public AccountEntry Entry {get; set;} 
}

public class AccountEntry { 
   public int id {get; set;}
   public int AccountId {get; set;} // 添加外键,关联Account的id
   public DateTime date {get; set;}
   public string description {get; set;}
   public decimal hour {get; set;}
   public Account Account {get; set;} // 可选:添加反向导航属性
}

第二步:在DbContext中配置关系

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Account>()
        .HasOne(a => a.Entry)
        .WithOne(ae => ae.Account)
        .HasForeignKey<AccountEntry>(ae => ae.AccountId);
}

之后结合方法1的Include查询,就能稳定获取包含嵌套对象的完整记录。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:20:28