virtual
关键字在EF Code First中的属性上使用时是否有效?有人可以在不同的情况下描述它的所有后果吗?
例如,我知道它可以控制lazy loading - 如果你在ICollection / one-to-many关系属性上使用virtual关键字,默认情况下它将是延迟加载的,而如果你离开虚拟关键字输出,它将被急切加载。
virtual
关键字在EF中与POCO实体有什么其他影响?我应该默认在我的所有属性上使用virtual
,还是默认不使用它?
答案 0 :(得分:186)
到目前为止,我知道这些影响。
virtual
ICollections将被延迟加载,除非您另外特别标记它们。More efficient change tracking。如果您满足以下所有要求,那么您的更改跟踪可以通过挂钩您的虚拟属性来使用更有效的方法。从链接:
要获取更改跟踪代理,请执行此操作 基本规则是你的班级必须是 公开的,非抽象的或非密封的。 你的班级也必须实施公开 所有人的虚拟getter / setter 持久化的属性。 最后,您必须声明收集 基于关系的导航 属性仅为
ICollection<T>
。 它们不可能是具体的 实现或其他接口 源自ICollection<T>
(a 与递延加载的差异 代理)
描述这一点的另一个有用链接是MSDN的Requirements for Creating POCO Proxies。
答案 1 :(得分:57)
此虚拟关键字与从实体框架加载数据的主题相关(延迟加载,急切加载和显式加载)。
如果要使用延迟加载加载数据,则应使用 虚拟 关键字。
延迟加载是在第一次访问实体或实体集合时自动从数据库加载的过程。
例如,当使用下面定义的Blog实体类时,将在第一次访问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();
}