虚拟关键字在Entity Framework 4.1 POCO Code First中有什么影响?

Sco*_*ord 223 entity-framework-4 ef-code-first entity-framework-4.1

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

例如,我知道它可以控制延迟加载 - 如果你在ICollection/one-to-many关系属性上使用virtual关键字,默认情况下它将是延迟加载的,而如果你将虚拟关键字保留为out,它将会急切的.

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

Sco*_*ord 190

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

  • 延迟加载:任何virtualICollections将被延迟加载,除非您特别标记它们.
  • 更有效的变更跟踪.如果您满足以下所有要求,那么您的更改跟踪可以通过挂钩您的虚拟属性来使用更有效的方法.从链接:

    要获得更改跟踪代理,基本规则是您的类必须是公共的,非抽象的或非密封的.您的类还必须为持久化的所有属性实现公共虚拟getter/setter.最后,您必须仅声明基于集合的关系导航属性ICollection<T>.它们不能是具体实现或源自的其他接口ICollection<T>(与延迟加载代理的区别)

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

  • 没有其他理由使属性成为虚拟.对于延迟加载,导航属性被标记为虚拟,而标量属性被标记为虚拟以进行更改跟踪. (52认同)
  • 什么是导航属性以及什么是标量属性? (9认同)
  • bytes []将被急切加载,只有外键可以是懒惰的.如果您不想获取该列,则永远不要获取整个记录 - 只需`.选择(a => new {fields you want})`. (9认同)
  • @AbidAli:我认为导航属性是外键(实体类类型)或一对多关系(类型为ICollection <>).标量属性是基类型(int,string,..)或ComplexType(它只是基类型的结构). (8认同)
  • 是"`public virtual byte [] bigData {get; set;}`"延迟加载? (2认同)

Par*_*rsa 58

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

如果要使用延迟加载加载数据,则应使用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; }  
}
Run Code Online (Sandbox Code Playgroud)

可以通过使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(); 
}
Run Code Online (Sandbox Code Playgroud)

明确加载:

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

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