virtual关键字在Entity Framework 4.1 POCO Code First中可以产生什么作用?


229

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

例如,我知道它可以控制延迟加载 -如果您在ICollection /一对多关系属性上使用virtual关键字,则默认情况下将对其进行延迟加载,而如果不使用virtual关键字,它将渴望加载。

virtual关键字在POCO实体的EF中还能产生什么其他影响?我应该将其默认设置为virtual在所有属性上使用,还是默认为不使用它?

Answers:


194

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

  • 延迟加载virtual除非您另外特别标记,否则所有ICollection都将被延迟加载。
  • 更有效的变更跟踪。如果满足以下所有要求,则更改跟踪可以通过挂接虚拟属性来使用更有效的方法。从链接:

    要获得变更跟踪代理,基本规则是您的课程必须是公开的,非抽象的或非公开的。您的班级还必须为所有持久化的属性实现公共虚拟获取器/设置器。最后,您必须仅声明基于集合的关系导航属性ICollection<T>。它们不能是具体的实现,也不能是衍生自的其他接口ICollection<T>(与Deferred Loading代理的区别)

描述此的另一个有用链接是MSDN的创建POCO代理要求


52
没有其他理由可以使属性虚拟化。对于延迟加载,将导航属性标记为虚拟,对于更改跟踪,将标量属性标记为虚拟。
Ladislav Mrnka

10
导航属性是什么,标量属性是什么?
阿比德·阿里

9
@AbidAli:我相信导航属性是外键(实体类类型)或一对多关系(类型为ICollection <>)。标量属性是基本类型(int,string,..)或ComplexType(这只是基本类型的结构)。
斯科特·斯塔福德,2012年

2
是“ public virtual byte[] bigData { get; set; }”延迟加载吗?
AechoLiu 2013年

9
bytes []将被急切加载,只有外键可以是惰性的。如果您不想获取该列,则永远不要获取整个记录-just .Select(a=>new { fields you want })
斯科特·斯塔福德,

63

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

如果要通过延迟加载来加载数据,则应使用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(); 
}

1
使用虚拟(延迟加载)时如何避免N + 1问题?例如,context.Blogs.ToList(); 那么它将不会联接表,并且它将运行与博客数量一样多的select查询。
专家想成为

1
@Expertwannabe即使您使用延迟加载,您仍然可以通过调用来显式请求快速加载Include()
先生
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.