为什么导航属性在EF中默认为虚拟

Sun*_*nil 40 entity-framework navigation-properties

我在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; }  
}
Run Code Online (Sandbox Code Playgroud)

Cla*_*ies 80

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

在某些情况下,最好使用"Eager Loading",尤其是如果您知道在某些时候您将与相关对象进行交互.

Julie Lerman确实是所有实体框架的权威,她在MSDN文章揭秘实体框架策略:加载相关数据中很好地解释了这个过程

使用Include进行预先加载对于您事先知道要查询所有核心数据的相关数据的情况非常有用.但要记住两个潜在的缺点.如果您有太多包含或导航路径,实体框架可能会生成性能不佳的查询.由于易于使用Include进行编码,因此您应该注意返回比必要更多的相关数据.

延迟加载非常方便地为您在幕后检索相关数据,以响应仅提及相关数据的代码.它也使编码更简单,但你应该认真对待它与数据库的相互作用.当只需要一两个时,您可能会导致40次访问数据库.

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

  • 我不太同意在网络应用程序中延迟加载不是有益的.即使每次在无状态应用程序中创建新上下文,不同的存储库调用也可能需要来自相同上下文的不同数据.例如,对于相同的Orders聚合根,您可能希望这次加载Products集合,而在另一个方法中加载ShippingStatusHistory集合.在上下文dbset级别上延迟加载允许您选择不同方法的不同数据. (3认同)