[英]dynamic proxies / lazy loading for entities doesn't work all the time in ef6
我正在将 EF6 与我的 Web 应用程序一起使用,并试图阐明急切加载/延迟加载的工作原理。 从我的研究来看,如果我想要动态代理,我必须将属性标记为“虚拟”。 此外,似乎默认情况下启用了动态代理。 我没有在我的数据库上下文中禁用延迟加载或动态代理加载。 我有一个例子:
//action method which is passed in a projectId
var project = dbContext.Projects.SingleOrDefault(p => p.Id == projectId);
//inspect project by setting debug point here.
public class Project{
public Client Client{get;set;} // this has a dynamic proxy created when loading
public System System{get;set;} // this property is just null
}
通常我必须通过以下方式解决这个问题:
dbContext.Projects.Include(p => p.System).SingleOrDefault(p => p.Id == projectId);
是什么赋予了? 有人可以为我揭开这个神秘面纱吗?
为确保启用延迟加载代理,您需要将属性声明为virtual
属性,并确保未在 DbContext 上禁用延迟加载。
您可能看到的行为是由于 dbContext 已经获取到相关实体之一并将其自动关联到您请求的相关实体。
让我们以一个项目(ID#1)和一个客户(ID#1)为例
如果您执行以下操作:
using ( var context = new MyDbContext())
{
var project = context.Projects.Single(x => x.Id == 1);
Console.WriteLine("Has Client: " + (project.Client != null).ToString());
}
如果没有virtual
你会得到“有客户端:假”。 使用virtual
控制台语句将触发对数据库的第二次查询,然后返回“有客户端:真”。
现在,事情变得有趣了:
using ( var context = new MyDbContext())
{
var tempClient = context.Clients.Single(x => x.Id == 1);
var project = context.Projects.Single(x => x.Id == 1);
Console.WriteLine("Has Client: " + (project.Client != null).ToString());
}
在这种情况下,我们的上下文只是加载对客户端 ID #1 的引用。 我们不做任何其他事情或将它与我们的项目引用相关联,我们只是像以前一样加载项目。 在这种情况下,输出将是“Has Client: True”,即使我们不急切加载它,并且它没有被标记为virtual
。 由于项目#1 有对客户#1 的引用,而客户#1 已被DbContext 跟踪,因此在我们请求项目#1 时会包含该引用。
这是使用长时间运行的 DbContexts 的结果,它可能导致应用程序中完全取决于情境的相当不可预测的行为。 您需要注意长时间运行,甚至请求有界 DbContext 实例,因为这可能导致获得不完整的数据图片。 例如,如果您有一个带有子级引用的父级,其中父级 #1 有 3 个子级。 (#1、#2 和 #3)如果您的上下文由于任何原因已加载并正在跟踪子级 #1 和 #2,并且您稍后加载父级 #1 而不急于加载子级,则该父级的 Children 集合将只列出 2 3 个子项(#1 和 #2)中的一个,这可能会给您的客户提供不完整和不准确的数据视图。 (当客户“有时”无缘无故地看到不完整的数据时,可以跟踪有趣的错误。)
通常,建议确保所有引用都标记为virtual
并尽可能缩短 DbContext 的生命周期。 我建议使用一个工作单元模式,它可以被注入并且生命周期范围限定于请求,但负责为 DbContext 本身创建更严格的生命周期范围,类似于using (var context = new MyDbContext())
而无需将代码绑定到 DbContext。
根据 本教程,动态代理是在以下情况下创建的:
ICollection <T>
类型。 您的System
类是否满足所有这些条件?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.