场景:
今天发现有一个查询很慢,根据Id对单条数据进行查询要300ms,这个完全是不正常的。然后断点进去看,发现,居然把里面所有的 virtual ICollection 的所有数据(这条数据大概有5个virtual ICollection 字段)都加载了。
问题:
之前,很多的文章都说, virtual ICollection<T> 就可以实现延迟加载,那么为什么这里会加载所有的数据出来。
查完一些资料后,我做了以下实验:
准备工作:创建一个控制台应用程序;通过Nu
get安装EF6,VS2015
创建Model,UserInfo以及DepartmentInfo ,DepartmentInfo 跟UserInfo是一对多的关系。
代码如下:
DepartmentInfo
1 public class DepartmentInfo2 {3 [Key]4 public int Id { get; set; }5 6 public string Name { get; set; }7 8 public ICollection<UserInfo> UserInfos { get; set; }9 }
UserInfo
1 public class UserInfo2 {3 [Key]4 public int Id { get; set; }5 6 public string Name { get; set; }7 }
TestEFDbContext
public TestEFDbContext() : base("TestConn") { } public DbSet<UserInfo> UserInfos { get; set; } public DbSet<DepartmentInfo> DepartmentInfos { get; set; }
实验1:DbContext、DepartmentInfo代码不变,DepartmentInfo的UserInfos前面不加virtual。
实验结果如下:
结论:在Department的UserInfos前面不加virtual的情况下,UserInfos没有被加载。
实验2:DbContext、DepartmentInfo代码不变,DepartmentInfo的UserInfos前面不加virtual。
在查询语句添加上Include
实验结果如下:
结论:通过Include,实现UserInfos加载。
实验3:修改DepartmentInfo代码
在DepartmentInfo中的UserInfos添加virtual关键字,
修改后的代码如下
实验结果如下:
结论,在加上添加了Virtual之后,UserInfos直接被加载进来了。
实验4:修改DepartmentInfo代码
在DepartmentInfo中的UserInfos添加virtual关键字,如实验3,
然后在TestEFDbContext的构造函数加上 this.Configuration.LazyLoadingEnabled = false;
实验结果如下:
结论,在加上添加了Virtual之后TestEFDbContext的构造函数加上 this.Configuration.LazyLoadingEnabled = false,UserInfos没有被加载。
实验5:修改DepartmentInfo代码
在DepartmentInfo中的UserInfos添加virtual关键字,如实验3,
然后在TestEFDbContext的构造函数加上 this.Configuration.LazyLoadingEnabled = false;(如实验4)
最后在查询语句添加上Include,
实验结果如下:
结论:通过Include,实现UserInfos加载。
如果要通过添加virtual实现按需加载数据,则需要TestEFDbContext的构造函数加上 this.Configuration.LazyLoadingEnabled = false;
或者是,不加Virtual以及this.Configuration.LazyLoadingEnabled = false;
显然,不加Virtual以及this.Configuration.LazyLoadingEnabled = false;更方便。
那么,Virtual的作用是什么?为什么那么多的文章都是推荐添加Virtual
原标题:关于EF中virtual ICollection 的一点问题
关键词: