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

附加到多个DbContext的实体的引用相等性技术问询

跨DbContext附加实体后的引用相等性分析

这个问题问到点子上了,刚好戳中EF Core上下文缓存的核心逻辑——我来给你拆解清楚:

首先得明确一个核心前提:每个DbContext的ChangeTracker(实体缓存)是完全独立的。单个上下文内的实体引用相等,本质是EF会优先从自己的缓存里返回已存在的实例,而非每次查询都新建对象。那跨上下文附加的情况,得分两边来看:

  • 对于手动附加了实体的dbContext2:
    当你把来自dbContext1的实体实例附加到dbContext2后,这个实例就被存入了dbContext2的ChangeTracker缓存。之后你在dbContext2里查询同一数据库对象(比如用dbContext2.Entities.Find(id)或者LINQ查询),EF Core会直接从缓存里返回你之前附加的那个实例,所以此时查询结果和你附加的实体是引用相等的。

  • 对于原始的dbContext1:
    dbContext1的缓存和dbContext2完全隔离,它只会维护自己范围内的实体实例。之后你在dbContext1里查询同一数据库对象,EF Core还是会从它自己的缓存里返回最初的那个实例——这个实例和dbContext2里的那个是不同的引用,因为两个上下文各自持有独立的实体对象。

举个简单的代码例子帮你理解:

// 从dbContext1获取实体
var entityFromDb1 = dbContext1.Entities.First(e => e.Id == 1);

// 附加到dbContext2
dbContext2.Entities.Attach(entityFromDb1);

// dbContext2查询同一实体
var entityFromDb2Query = dbContext2.Entities.Find(1);
Console.WriteLine(entityFromDb1 == entityFromDb2Query); // 输出 True(引用相等)

// dbContext1再次查询同一实体
var entityFromDb1Query = dbContext1.Entities.Find(1);
Console.WriteLine(entityFromDb1 == entityFromDb1Query); // 输出 True(单个上下文内的引用相等)
Console.WriteLine(entityFromDb1 == entityFromDb2Query); // 输出 False(跨上下文的引用不同)

补充个小细节:不管你在dbContext2里用Attach()还是Entry(entity).State = EntityState.Unchanged这类方式附加实体,本质都是把这个实例纳入dbContext2的缓存,后续查询都会复用它。但无论如何,dbContext1和dbContext2的缓存不会共享实例,所以两边的实体引用永远不会相等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:37:35