【发布时间】:2021-01-04 19:05:04
【问题描述】:
我之前编写的一些代码使用Find() 方法通过主键检索单个实体:
return myContext.Products.Find(id)
这很有效,因为我将这段代码放入了一个泛型类中,并且每个实体都有不同的字段名称作为其主键。
但我不得不替换代码,因为我注意到它正在返回缓存数据,并且我需要它在每次调用时从数据库中返回数据。微软的文档证实这是Find()的行为。
所以我将代码更改为使用SingleOrDefault 或FirstOrDefault。我没有在文档中找到任何说明这些方法返回缓存数据的内容。
现在我正在执行这些步骤:
- 通过 EF 保存实体。
- 在 SSMS 中执行 UPDATE 语句来更新最近保存的 记录的描述字段。
- 使用
SingleOrDefault将实体检索到新的实体变量中 或FirstOrDefault。
返回的实体在 Description 字段中仍然具有旧值。
我已运行 SQL 跟踪,并验证在第 3 步期间正在查询数据。这让我感到困惑 - 如果 EF 正在往返于数据库,为什么它会返回缓存数据?
我在网上搜索过,大多数答案都适用于Find() 方法。此外,他们提出了一些解决方案,这些解决方案仅仅是变通方法(处理 DbContext 并实例化一个新的)或对我不起作用的解决方案(使用 AsNoTracking() 方法)。
如何从数据库中检索我的实体并绕过 EF 缓存?
【问题讨论】:
-
工作单元意味着如果你在上下文中有实体,你将从上下文中接收实体;因此 EF 在 DB 中找到实体并使用该 ID 从上下文中返回实体。你有很多选择,比如在查询之前从上下文中分离“缓存”实体,或者将实体加载到新上下文然后附加它等等,但是所有这些变通方法都在喊“你用错了”
-
如果没有更多信息,我同意@Lanorkin。这很少成为问题的原因是因为
DbContext对象应该有范围并且生命周期很短(比如只有一个 HTTP 请求的生命周期)。在这么短的时间内,没有理由返回数据库两次获取相同的记录。我怀疑你的DbContext对象已经存在太久了。 -
你找到合适的解决方案了吗@ChadSC???