2013-09-26 28 views
4

我有一個返回值IQueryable使用LINQ當在LINQ中執行時,表達式是否枚舉參數?

return eventFacade.GetNewBuildingEvents() 
       .Where(EventPredicates.IsBuildingOwner(
         memberFacade.GetFriendsAndColleagues(m).Select(y => y.Id)) 
     ) 

GetFriendsAndColleagues(m).Select(y => y.Id)返回一個IEnumerable

 public static Expression<Func<Event, bool>> IsBuildingOwner(IEnumerable<int> friendids) 
    { 
     return 
      x => 
       x.Building.BuildingMembers.Where(k => k.Type == MemberType.Owner) 
        .Any(p => friendids.Contains(p.Member.Id)); 
    } 

我仍然在學習LINQ和C#在一般的方法。我知道IQueryableIEnumerable都推遲執行,並且我知道在數據庫中使用IQueryable進行過濾,而IEnumerable發生在內存中。

我也知道,在一個迭代集合的情況下,最好枚舉集合,以便每次迭代都不會調用數據庫。

所以在執行我的最終查詢請問IEnumerable傳遞到我的表達得到列舉一次,然後使用由GetNewBuildingEvents()

返回的每個項目比較它使在每個數據庫中調用比較得到清單?

+0

「GetNewBuildingEvents」的實現和返回類型是什麼?什麼是IQueryable提供程序?無論如何,我相信或者它是LINQ對實體或IQueryable將拋出一個異常。 – gdoron

+0

我在查詢中使用.AsEnumerable(),稍後在方法中將其轉換爲另一個對象。如上所述的查詢編譯並運行良好 –

+0

你是專門詢問Linq到SQL/DB的權利嗎?由於AFAIK,您可以同時使用IQueryable和IEnumerable,以便LINQ to Objects以及Linq to DB。最終實際運行的是LINQ提供者。 – Vivek

回答

3

如果您想知道它的迭代次數,只需在一個序列上運行該代碼,該序列在迭代時會執行一些可觀察的副作用,以便您可以看到它發生了多少次。

您可以使用以下幫助器方法將任何序列封裝到每次迭代時都會寫入控制檯的序列中。

public static IEnumerable<T> NoisyWrapper<T>(IEnumerable<T> source) 
{ 
    Console.WriteLine("Rabble rabble rabble!!!"); 
    foreach (var item in source) 
     yield return item; 
} 

這樣就解決了一般情況下的問題。

在特定情況下,序列只應迭代一次。您正在創建一個表達式,該表達式被編譯爲數據庫查詢並在數據庫端執行。將IEnumerable中的Contains與大多數基於SQL的查詢提供程序在相應的上下文中使用(您的是),將被轉換爲SQL中的IN子句。 IEnumerable將需要迭代一次以提供IN子句的值,並且不需要重複多次。

+0

太棒了!謝謝,這只是我正在尋找的解釋。 –