Entity Framework如何使用代理类来支持延迟加载?

How Entity Framework uses proxy classes to support lazy loading?

我想了解 Entity Framework 如何使用 Proxy 类?为什么 Entity Framework 需要代理 类?启用延迟加载时,幕后实际发生了什么?感谢您的帮助!

在过去 POCO 之前,EF 中的实体 class 继承自 EntityObject。这对旧的 ObjectContext 更改跟踪器等有一些 tie-ins,并且可以提供(我认为)执行导航属性延迟加载等操作所需的一些功能。

随着 POCO(plain-old CLR 对象)的出现,class 继承消失了。由此得名。这意味着您的实体 classes 只有您放入其中的代码。

当您编写导航 属性 时,它通常类似于:

public virtual Course Course { get; set; }

非常基础,没有 getter/setter 代码。这意味着默认情况下它不会像延迟加载那样做任何花哨的事情。它不知道如何。

输入proxy/wrapper class:它有代码来做像延迟加载这样的事情。

我认为主要代码是EntityProxyFactory and EntityProxyTypeInfo,它似乎创建了代理工厂使用的baseGetterbaseSetter表达式。它使用来自代理类型的 MethodInfo 创建表达式...我还没有找到该代码...我认为这才是真正的工作完成的地方。

此外,这是针对 EF6 的...EF 核心代码位于不同的存储库中。

我对 EF 代码的了解还不够深入,无法知道这是否正是它正在做的事情,但是您手动加载导航 属性 的方式是通过更改跟踪器条目,如下所示:

using var db = new BloggingContext();
var blog = db.Blogs.First();
// get change tracker entry for blog
var entry = db.Entry(blog);
// load the blog.Posts navigation property
entry.Reference(x=> x.Posts).Load();
// now you can use blog.Posts!

我猜它正在做与此等效的事情。

它是一个 decorator 通过 -

为实体对象添加延迟加载功能
  • 存储对上下文的引用。
  • 使用上下文覆盖导航属性以使其在访问时加载。

代理继承自实体class。因此,导航属性必须是 virtual 而实体 class 不能是 sealed.

也许了解它们的最有指导意义的方法是查看实施 lazy loading without proxies.

需要什么