首页 > 解决方案 > DbContext:延迟加载不必要的数据库调用?

问题描述

我有一个非常基本的示例 C# 程序,它使用 EF6 和 DbContext 并包含两个类:

MyTable1   1...n   MyTable2

我有以下代码:

// Creation of instances and saving them to the database.
using (var context = new EFTestEntities()) {
  var myTable1 = new MyTable1() { ID = 1 };
  var myTable2 = new MyTable2() { ID = 2 };
  myTable1.MyTable2.Add(myTable2);
  context.MyTable1.Add(myTable1);
  context.SaveChanges();
}

// Getting the above objects in another context.
// This part here is what my question is about.
using (var context = new EFTestEntities()) {
  var myTable1 = context.MyTable1.Where(e => e.ID == 1).FirstOrDefault();
  var myTable2 = context.MyTable2.Where(e => e.ID == 2).FirstOrDefault();
  var myTable2AssignedToMyTable1 = myTable1.MyTable2.FirstOrDefault();
}

我的问题是关于上面代码的第二部分。

启用延迟加载后,我会收到三个数据库调用。每行一个。变量myTable2AssignedToMyTable1包含 then myTable2- 这是正确的。

禁用延迟加载后,我会收到两个数据库调用。一个用于第一行,一个用于第二行。该变量myTable2AssignedToMyTable1也包含myTable2- 没有第三个数据库调用。这对我来说很有意义,因为myTable2在第 2 行加载。

但是:如果不需要第三个数据库调用,为什么在启用延迟加载时进行?

当我在 SQL Server Profiler 中检查有无延迟加载的数据库调用时,我意识到它们完全相同(除了第三次调用)。第三次调用的数据与第一次或第二次调用的数据相同。因此,当第三次调用发生时,所需的数据已经在上下文中。当延迟加载被禁用时,EF 会实现它并使用已经加载的数据。当启用延迟加载时,它不会意识到它并再次从数据库中获取相同的数据。为什么?

它比MyTable2在上下文中找到正确的实例更快吗?

还是比总是先在上下文中搜索正确的实例然后进行数据库调用更快?可以假设在大多数情况下所需的数据尚未在上下文中。所以我猜 EF 设计者决定不先检查上下文。在大多数情况下,无论如何都会错过。

但这些只是我的假设。知道真正的原因会很有趣。

标签: c#entity-framework-6lazy-loadingdbcontext

解决方案


推荐阅读