ICollection上的AsQueryable()是否真的会执行延迟执行?

我正在使用Entity Framework CodeFirst,我使用ICollection作为父子关系

public class Person { public string UserName { get;set} public ICollection Blogs { get; set;} } public class Blog { public int id { get; set; } public string Subject { get; set; } public string Body { get; set; } } 

好吧,到目前为止一切正常,但我担心的是,每当我想得到一个人的博客时,我就把它当作

 var thePerson = _context.Persons.Where(x => x.UserName = 'xxx').SingleOrDefault(); var theBlogs = thePerson.Blogs.OrderBy(id).Take(5); 

现在,我明白,当执行该行时,该人的所有博客都会加载到内存中,然后从内存中进行排序和选择。 这对于拥有大量博客的人员的记录来说并不理想。 我想将Blog Child设为IQueryable,以便在拉到Memory之前在SQL数据库中完成排序和选择。

我知道我可以在我的上下文中将Blogs声明为IQueryable,以便我可以直接查询为

 var theBlogs = _context.Blogs.Where(.....) 

但由于设计选择,这对我来说是不可行的,因为序列化问题,我想尽可能避免任何循环引用。 所以,我没有在我孩子的父母实体中做任何参考。

我发现,我可以在博客上调用AsQueryable()方法

 var theBlogs = thePerson.Blogs.AsQueryable().OrderBy(id).Take(5); 

这对我来说似乎是一种魔力,看起来好得令人难以置信。 所以我的问题。 这个AsQueryable是否真的使ICollection成为现实中的IQueryable并在SQL Server中进行所有查询过程(延迟加载)或者它只是将博客像以前一样加载到内存中,但是将接口从ICollection更改为IQueryable?

实际上,似乎无法将导航属性写为IQueryable

您可以做的是向Blog添加导航属性:

 public class Blog { public int id { get; set; } public string Subject { get; set; } public string Body { get; set; } public virtual Person Owner { get; set; } } 

从那里,你可以查询如下,所以它不会将所有内容加载到内存中:

 var thePerson = _context.Persons.Where(x => x.UserName = 'xxx').SingleOrDefault(); var results = _context.Blogs.Where(z => z.Person.Name = thePerson.Name).OrderBy(id).Take(5) 

我建议你试试LINQPad ,看看LINQ是如何被翻译成SQL的,以及DB实际要求的是什么。

Ladislav的答案描述了一种更好的方法。 在你的情况下:

 var theBlogs = _context.Entry(thePerson) .Collection(x => x.Blogs) .Query() .OrderBy(x => x.id) .Take(5);