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

Emr*_*ain 8 c# iqueryable icollection ef-code-first entity-framework-4.1

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

public class Person
{
   public string UserName { get;set}
   public ICollection<Blog> Blogs { get; set;}
}

public class Blog
{
   public int id { get; set; }
   public string Subject { get; set; }
   public string Body { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

var theBlogs = _context.Blogs.Where(.....)
Run Code Online (Sandbox Code Playgroud)

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

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

var theBlogs = thePerson.Blogs.AsQueryable().OrderBy(id).Take(5);
Run Code Online (Sandbox Code Playgroud)

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

ken*_*n2k 6

实际上,似乎IQueryable<T> 无法编写导航属性.

你可以做的是添加一个导航属性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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我建议您尝试使用LINQPad来查看LINQ如何转换为SQL,以及DB实际请求的内容.