这里是一些代码以及我基于在 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);
- 检索一些记录(查询数据库)。
- 检索恰好是
record
的外键属性的记录,而不使用像record.ForeignKey
这样的延迟加载来检索它(查询数据库)。 - 获取
record
实体的详细信息。 - 这是我不确定的部分。在我的测试中,它输出
true
。我猜 IsLoaded 不知道record.ForeignKey
当前是否有值,但知道record.ForeignKey
已经在上下文中基于它是关于record.ForeignKeyId
和已建立的关系的知识。 - 数据库似乎没有被击中,我认为这是出于同样的原因
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
标志控制。如果将导航属性的实体附加到上下文,则延迟加载不会再发生,尽管 IsLoaded
为 false
。
如果第二个代码片段中的最后一行实际上会触发延迟加载,会发生什么情况?正在加载的 ForeignKey
对象必须与您已附加的 ForeignKey
对象具有相同的键(因为 record
具有此值作为 FK 属性 ForeignKeyId
).但是因为没有两个具有相同键的对象可以附加到上下文,所以它必须是同一个对象。但是不需要加载它,因为这样的对象已经在内存中并已附加。
关于c# - 我对 IsLoaded 的理解是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8525880/