Jit*_*hal 2 .net c# collections ienumerable iqueryable
我有以下型号 -
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public Nullable<int> StandardId { get; set; }
public virtual Standard Standard { get; set; }
}
public class Standard
{
public int StandardId { get; set; }
public string StandardName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
关系是 - >一个标准可以有多个学生.当使用IEnumerable执行下面的代码时,它会执行延迟加载,如下面的日志所示
码-
using (var ctx = new SchoolDBEntities())
{
ctx.Database.Log = Logger.Log;
IEnumerable<Student> studList = ctx.Students;
foreach(Student std in studList)
{
Console.WriteLine("Student Name = " + std.StudentName);
//Loads Student standard for particular Student only (separate SQL query)
Standard standard = std.Standard;
Console.WriteLine("Standard Name = " + standard.StandardName);
}
}
Run Code Online (Sandbox Code Playgroud)
从日志中可以看出,在需要时提取"标准"表数据.那么为什么说IEnumerable不支持Laze Loading和IQueryable呢?
当我使用IQueryable代替IEnumerable运行代码时,它显示相同的日志.我没有找到任何解释IEnumerable如何不支持延迟加载的示例.
Den*_*nis 10
那么为什么说IEnumerable不支持Laze Loading
延迟加载是ORM概念(在您的情况下是实体框架).
您可以将其视为实现细节.
既不支持IEnumerable<T>也不IQueryable<T>支持延迟加载.
IEnumerable<Student> studList = ctx.Students;
Run Code Online (Sandbox Code Playgroud)
无论变量 type(IEnumerable<Student>)如何,引用的对象类型都将DbSet<Student>实现IQueryable<Student>.
DbSet<T>使用EF基础设施来实现对象.延迟加载由代理类型实现,由EF对象材质生成器生成.这不是IEnumerable<T>或没有IQueryable<T>特色.
PS
如上所述,延迟执行!=延迟加载.
IEnumerable<T>并IQueryable<T>支持延期执行.对于IQueryable<T>这意味着,查询将被执行,对象将被物化,只有当你将开始枚举查询结果.
但这不是延迟加载.Student.Standard将被加载,当你打电话给属性getter.这是延迟加载.正如您所看到的,它与之相关IQueryable<T>:您不需要IQueryable<T>调用属性getter.
这是关于运行时与编译时类型,以及集合与它包含的对象。
当您执行查询可以分配给一个IEnumerable<T>变量时,它仍然是一个IQueryable<T>底层。
但是,一旦您IEnumerable<T>在其上使用方法,该集合将不再是可查询的。例如。呼叫ToArray或ToList。
这样做的主要影响是进一步的操作(例如Where过滤)将发生在内存中,而不是更改查询。
然而,这与 EF 关联(std.Standard在您的代码中)的惰性属性无关,它是在集合中的单个对象上完成的,而不是集合。
所以如果你有
var qry = /* something to create an IQueryable<T> from your DbContent */
foreach (var x in qry) {
// qry has been enumerated: so SQL has been generated and executed
}
qry = qry.Where(some-condition);
foreach (var x in qry) {
// qry has been enumerated: SQL with extra condition applied is run
}
var e = qry.ToList();
// Anything done to e is done in memory, there will be no new
// SQL sent to the DB for the collection/
var f = e.First();
// But, as Standard is a lazy property this will generated a query.
x = e.Standard.SomeProperty;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3202 次 |
| 最近记录: |