8

我使用實體框架CodeFirst,我已經使用使用ICollection的親子關係作爲ICollection上的AsQueryable()是否確實會執行延遲?

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; } 
} 

好了,到目前爲止,一切工作正常,但我關心的是,每當我想一個人的博客,我把它作爲

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

現在,我的理解是,執行線的時候,那個人所有的博客被加載到內存中,然後排序和篩選是從內存中完成。這對於擁有大量博客的人的記錄來說並不理想。我希望將Blog Child設置爲IQueryable,以便在將數據提取到內存之前在SQL數據庫中完成排序和選擇。

我知道我可以聲明博客爲IQueryable的在我的背景下,這樣我可以直接查詢作爲

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

但這是不可行的我由於設計的選擇,我想避免任何循環引用作爲由於序列化問題,儘可能多。所以,我沒有提及我孩子的父母實體。

我發現,我可以在博客呼籲AsQueryable已()方法

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

這看起來就像是我一個神奇,似乎好得是真實的。所以我的問題。這個AsQueryable是否真的使ICollection成爲現實中的IQueryable並使所有查詢進程都在SQL Server中(延遲加載),或者它只是將博客像以前一樣加載到內存中的轉換,但將接口從ICollection更改爲IQueryable?

+2

後者,而不是前者。 – Enigmativity 2012-02-08 10:15:29

+0

謝謝 - Enigmativity,所以我的懷疑是真的。這是可悲的。 – 2012-02-08 11:23:13

回答

6

所以實際上它看起來是編寫導航屬性爲IQueryable<T>is not possible

你可以做的是增加一個導航屬性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中請求的內容。

+0

非常感謝您的回覆。好吧,它的意思是,ICollection也是一個像IQueryable這樣的懶惰的加載器,我可以在任何地方安全地使用ICollection來代替IQueryable,我希望查詢應該在數據庫中進行。關於LINQPAD,我認爲這給出了有關SQL翻譯的理論,但也許一些EntityFramework Profiler可以更好地幫助我們更好地瞭解哪些QUERY正在數據庫中發送。我沒有任何實體框架分析器,但現在我正在研究一些這樣的產品。 – 2012-02-08 10:30:04

+0

只是另一個問題,所以如果我以前的問題的答案是YES,那麼,我不需要使用AsQueryable()了ICollection,對吧? – 2012-02-08 10:32:12

+1

+1用於推薦一種可以使開發LINQ查詢變得更容易的工具。 – 2012-02-08 10:33:44

2

更好的方法在Ladislav's answer中描述。在你的情況:

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