【问题标题】:Why Navigation Properties are virtual by default in EF为什么导航属性在 EF 中默认是虚拟的
【发布时间】:2014-11-01 03:42:05
【问题描述】:

我在 EF 6.x 中使用了以下 POCO 类。

我的问题:为什么“博客”实体下的“帖子”的导航属性声明为虚拟?

public class Blog 
{  
    public int BlogId { get; set; }  
    public string Name { get; set; }  
    public string Url { get; set; }  
    public string Tags { get; set; }  

    public virtual ICollection<Post> Posts { get; set; }  
}

【问题讨论】:

标签: entity-framework navigation-properties


【解决方案1】:

如果您定义导航属性virtual,Entity Framework 将在运行时创建一个从您的类派生的新类(动态代理)并使用它而不是您的原始类。这个新的动态创建的类包含在第一次访问时加载导航属性的逻辑。这被称为“延迟加载”。它使 Entity Framework 能够避免从数据库中加载不需要的依赖对象的整个树。

在某些情况下,最好改用“急切加载”,尤其是当您知道自己将在某个时候与相关对象进行交互时。

Julie Lerman 确实是 Entity Framework 的权威,她在她的 MSDN 文章 Demystifying Entity Framework Strategies: Loading Related Data

中很好地解释了这个过程

使用 Include 进行预加载对于您提前知道要查询所有核心数据的相关数据的场景很有用。但请记住这两个潜在的缺点。如果您有太多包含或导航路径,实体框架可能会生成性能不佳的查询。由于使用 Include 编码很容易,您应该小心返回不必要的相关数据。

延迟加载非常方便地在后台为您检索相关数据,以响应仅提及相关数据的代码。它也使编码变得更简单,但您应该认真考虑它与数据库的交互量。当只需要一两次时,您可能会导致 40 次访问数据库。

如果您正在开发的 Web 应用程序与服务器的每次通信都是一个新的上下文,那么延迟加载只会产生不必要的开销来维护永远不会加载的相关对象的动态类。许多人会在这些情况下禁用延迟加载。最终,最好还是评估 EF 构建的 SQL 查询,并确定哪些选项最适合您正在开发的场景。

【讨论】:

  • 我不太同意在网络应用程序中延迟加载无益的观点。即使每次在无状态应用程序中创建新的上下文,不同的存储库调用也可能需要来自同一上下文的不同数据。例如,对于相同的 Orders 聚合根,您可能希望这次加载 Products 集合,但在另一个方法中加载 ShippingStatusHistory 集合。在上下文 dbset 级别上进行延迟加载允许您在不同的方法上选择不同的数据。
猜你喜欢
  • 2017-06-12
  • 2015-05-30
  • 2010-11-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多