c# - 我对 IsLoaded 的理解是否正确?

标签 c# .net entity-framework ef-code-first change-tracking

这里是一些代码以及我基于在 LINQPad 中尝试的假设。任何人都可以确认这是延迟加载的工作方式,并可能提供任何其他见解/链接,以便我了解它在后端的工作方式吗?提前致谢!

// Step 1.
var record = context.MyTable.First();

// Step 2.
var foreignKey = ForeignKeyTable.Where(x => x.Id == record.ForeignKeyId).Single();

// Step 3.
var entry = context.Entry(record);

// Step 4.
trace(entry.Reference(x => x.ForeignKey).IsLoaded);

// Step 5.
trace(record.ForeignKey.SomeProperty);
  1. 检索一些记录(查询数据库)。
  2. 检索恰好是 record 的外键属性的记录,而不使用像 record.ForeignKey 这样的延迟加载来检索它(查询数据库)。
  3. 获取 record 实体的详细信息。
  4. 这是我不确定的部分。在我的测试中,它输出 true。我猜 IsLoaded 不知道 record.ForeignKey 当前是否有值,但知道 record.ForeignKey 已经在上下文中基于它是关于 record.ForeignKeyId 和已建立的关系的知识。
  5. 数据库似乎没有被击中,我认为这是出于同样的原因 IsLoaded 在 4 中返回 true。它知道它正在跟踪 foreignKey 对象已经,所以它知道它不必进行延迟加载。

编辑:我试图解决的实际问题可以这样说明:

var record = context.MyTable.First();

var foreignKey = new ForeignKey() { Id = record.ForeignKeyId, SomeProperty = 5 };
context.ForeignKeyTable.Attach(foreignKey);

var entry = context.Entry(record);

// Returns false.
trace(entry.Reference(x => x.ForeignKey).IsLoaded);

// Doesn't query for ForeignKey, so it must know it's `loaded` somehow, and
// gets SomeProperty from my new foreignKey object. What???
trace(record.ForeignKey.SomeProperty);

最佳答案

当您从数据库加载实体或将实体附加到上下文时,EF 会根据主键和外键值自动修复关系(导航属性)。

在这两个代码片段中,您都加载了 record,它具有指向您的 ForeignKeyTable 的外键。上下文知道这个值。 (顺便说一下,如果您在模型中公开了外键,这并不重要。它将始终被加载,即使您的模型中没有 FK 属性。您可以在查看 SQL 查询时看到这一点。)

在这两种情况下,您随后都会将 ForeignKey 实体附加到上下文,该实体的主键是上下文已知的 record.ForeignKeyId 的值。因此,EF 会将导航属性 record.ForeignKey 设置为此附加的 ForeignKey 实体。

显然 IsLoaded 不会告诉您实体是否已附加到上下文,因为在两个示例中它都已附加但一个返回 true 而另一个返回 false 。它也不会告诉您 record.ForeignKeyId 是否指代实体,因为这两个示例也是如此。

它显然只告诉您该实体确实已从数据库加载(而不仅仅是手动附加)(Intellisense 也说 IsLoaded)。这是您的第一个示例和第二个示例之间的唯一区别。

而且延迟加载似乎不仅仅由 IsLoaded 标志控制。如果将导航属性的实体附加到上下文,则延迟加载不会再发生,尽管 IsLoadedfalse

如果第二个代码片段中的最后一行实际上会触发延迟加载,会发生什么情况?正在加载的 ForeignKey 对象必须与您已附加的 ForeignKey 对象具有相同的键(因为 record 具有此值作为 FK 属性 ForeignKeyId).但是因为没有两个具有相同键的对象可以附加到上下文,所以它必须是同一个对象。但是不需要加载它,因为这样的对象已经在内存中并已附加。

关于c# - 我对 IsLoaded 的理解是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8525880/

相关文章:

c# - 使用各种类属性返回 Expression<>

C# 如何在循环中组合一些 Linq 表达式

c# - JWT 不记名 token 不适用于 ASP.Net Core 3.1 + Identity Server 4

sql-server - EF Core - 代码优先 - 多个级联路径

c# - LINQ 表达式失败,但 foreach 循环有效 Entity-Framework

c# - 对具有多个级别的 Dictionary<string,Object> 进行排序

c# - 需要帮助了解 List<T>.Sort(IComparer(T)) 如何知道要排序的值

.net - 用于单元测试的内存 DBMS

c# - 在添加迁移期间忽略来自引用程序集的实体

entity-framework - 如何解决 AutoMapper 错误? (stackoverflow 异常!)