virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生啥影响?

Posted

技术标签:

【中文标题】virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生啥影响?【英文标题】:What effect(s) can the virtual keyword have in Entity Framework 4.1 POCO Code First?virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生什么影响? 【发布时间】:2011-08-01 15:36:24 【问题描述】:

virtual 关键字在用于 EF Code First 中的属性时是否有效?有人可以描述它在不同情况下的所有后果吗?

例如,我知道它可以控制lazy loading -- 如果您在 ICollection/一对多关系属性上使用 virtual 关键字,默认情况下它将延迟加载,而如果您保留 virtual 关键字出来,它将被急切地加载。

virtual 关键字在带有 POCO 实体的 EF 中还有哪些其他影响?我应该默认在我的所有属性上使用virtual,还是默认不使用它?

【问题讨论】:

【参考方案1】:

到目前为止,我知道这些影响。

Lazy Loading:任何virtual ICollections 都将被延迟加载,除非您特别标记它们。

More efficient change tracking。如果您满足以下所有要求,那么您的更改跟踪可以通过挂钩您的虚拟属性来使用更有效的方法。从链接:

要获取更改跟踪代理, 基本规则是你的班级必须是 公开的、非抽象的或非密封的。 您的课程还必须实现 public 所有人的虚拟 getter/setter 持久化的属性。 最后,您必须声明集合 基于关系导航 仅限ICollection<T> 的属性。 它们不可能是具体的 实现或其他接口 源自ICollection<T>(一个 与延迟加载的区别 代理)

描述此问题的另一个有用链接是 MSDN 的 Requirements for Creating POCO Proxies。

【讨论】:

没有其他理由使属性虚拟化。导航属性标记为虚拟以进行延迟加载,标量属性标记为虚拟以进行更改跟踪。 什么是导航属性,什么是标量属性? @AbidAli:我相信导航属性是外键(实体类类型)或一对多关系(ICollection 类型)。标量属性是基本类型(int、string、..)或 ComplexType(它只是基本类型的结构)。 public virtual byte[] bigData get; set; ”是延迟加载吗? bytes[] 将被急切加载,只有外键可以是惰性的。如果您不想获取该列,请不要获取整条记录 - 只需 .Select(a=>new fields you want )【参考方案2】:

此虚拟关键字与从实体框架加载数据(延迟加载、急切加载和显式加载)的主题有关。

当您想通过延迟加载加载数据时,您应该使用 virtual 关键字。

延迟加载是一个实体或实体集合在第一次被访问时自动从数据库加载的过程。

例如,使用下面定义的 Blog 实体类时,相关的 Posts 将在第一次访问 Posts 导航属性时被加载:

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;   

可以通过将 Posts 属性设为非虚拟来关闭 Posts 集合的延迟加载。

如果关闭延迟加载,仍然可以使用预先加载(使用 Include 方法)或显式加载相关实体(使用 Load 方法)来加载 Posts 集合。

急于加载:

using (var context = new BloggingContext()) 
 
    // Load all blogs and related posts 
    var blogs1 = context.Blogs 
                          .Include(b => b.Posts) 
                          .ToList(); 

显式加载:

using (var context = new BloggingContext()) 
 
    var blog = context.Blogs.Find(1); 

    // Load the posts related to a given blog 
    context.Entry(blog).Collection(p => p.Posts).Load(); 

【讨论】:

使用虚拟(延迟加载)时如何避免N+1问题?例如,context.Blogs.ToList();那么它就不会加入表,它会运行与博客数量一样多的选择查询。 @Expertwannabe 即使您使用延迟加载,您仍然可以通过调用Include() 显式请求即时加载。

以上是关于virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

Dynamics 365 通过Virtual Entity和第三方的数据源集成二

Entity Frame Code First

virtual这个关键字有啥用

覆盖方法时 virtual 关键字是啥意思?

C# 关键字--virtual(转)

C++ 风格:为覆盖方法添加前缀 virtual 关键字