1

我瞭解到IQueryable或IEnumerable數據類型不會在第一時間返回結果,只會在需要時返回結果。但是,當我在手錶檢查員中打開該對象時,我看到所有對象都在那裏。EntityFramework:IQueryable或IEnumerable在第一個地方獲得所有結果嗎?

我的代碼有什麼問題,或者只是因爲我把它叫做手錶而顯示?

[當我在手錶對話框中查看掛件對象時,我看到了所有列表項,但它不應該加載到第一個位置。這有什麼錯在我接近,或者它只是顯示,因爲我已經把它的手錶]

public IQueryable<PurchasePendingView> PurchasePendings() { 
      var pendings = db.PurchasePendingViews 
          .Where(m => m.AccountStatusID != StructAccountStatus.Succeed); // when I view it in the watch dialougebox I saw all the list items but it shouldn't load at the first place. Is there anything wrong in my approaching or is it just showing because I had call it on the watch. 
      if (ApplicationEnvironment.DEBUGGING) { 
       return pendings; 
      } else if (IsMobileAccount()) { 
       var showroom = db.ShowRooms.FirstOrDefault(m=> m.MemberID == employee.MemberID); 
       if (showroom != null) { 
        return pendings.Where(m => m.ShowRoomID == showroom.ShowRoomID); 
       } else { 
        return pendings.Where(m => m.CountryDivisionID == employee.CountryDivisionID); 
       } 
      } else { 
       //normal salary employee can see every detail 
       return pendings; 
      } 
     } 

注:目前我的延遲加載是關閉的。

回答

5

在第一次迭代結果時評估集合。

由於您正在迭代手錶檢查器中的結果,因此它們將被刪除。

+1

這樣做是否意味着我的查詢實際上沒有在第一個地方加載任何東西,並在結束時將它們返回到它將加載的東西? – user1542653

+0

@ user1542653 - 不。這意味着您的方法返回IQueryable對象,然後結果將在第一次調用者迭代結果時加載。 –

+1

不,即使你返回它,它也不會加載,直到某些調用代碼迭代返回。 –

0

這種情況很容易表現出比解釋:

public class MeanException : Exception 
{ 
    public MeanException() : base() { } 
    public MeanException(string message) : base(message) { } 
} 
public static IEnumerable<T> Break<T>(this IEnumerable<T> source) 
    where T : new() 
{ 
    if (source != null) 
    { 
     throw new MeanException("Sequence was evaluated"); 
    } 
    if (source == null) 
    { 
     throw new MeanException("Sequence was evaluated"); 
    } 

    //unreachable 

    //this will make this an iterator block so that it will have differed execution, 
    //just like most other LINQ extension methods 
    yield return new T(); 
} 

public static IEnumerable<int> getQuery() 
{ 
    var list = new List<int> { 1, 2, 3, 4, 5 }; 

    var query = list.Select(n => n + 1) 
     .Break() 
     .Where(n => n % 2 == 0); 

    return query; 
} 

那麼,我們有什麼在這裏。我們有一個自定義異常,所以我們可以獨立地捕捉它。我們有一個IEnumerable<T>的擴展方法,它會在序列評估結束後立即拋出異常,但它使用延遲執行,就像SelectWhere一樣。最後我們有一個方法來獲取查詢。我們可以在調用Break之前和之後看到LINQ方法,我們可以看到List被用作底層數據源。 (在你的榜樣它可以是在內存中的一些集合,或者一個目標,會去查詢數據庫,然後迭代時遍歷結果。)

現在讓我們使用這個查詢,看看會發生什麼:

try 
{ 
    Console.WriteLine("Before fetching query"); 
    IEnumerable<int> query = getQuery(); 
    Console.WriteLine("After fetching query"); 
    foreach (var number in query) 
    { 
     Console.WriteLine("Inside foreach loop"); 
    } 
    Console.WriteLine("After foreach loop"); 
} 
catch (MeanException ex) 
{ 
    Console.WriteLine("Exception thrown: \n{0}", ex.ToString()); 
} 

如果您運行此代碼,您將看到的是打印之前的查詢(顯然)查詢後的打印(意味着我們剛剛從方法返回查詢並且平均異常從未拋出),接下來顯示的消息拋出異常(這意味着我們永遠不會進入foreach循環的內部或結尾)

這顯然是一個bi這是一個人爲的例子來展示一個概念,但這是你在實踐中經常看到的東西。例如,如果在創建數據上下文後失去與數據庫的連接,則在迭代查詢之前,或者如果數據持有者對象過期並且不再與數據庫匹配,實際上不會發生異常在同一時間會得到例外。在一個不太明顯的例子中,如果你持續查詢一段時間,那麼當你獲取查詢結果時,最終會得到數據,而不是當你構建它時。這裏是另一個演示:

var list = new List<int> { 1, 2, 3, 4, 5 }; 

var query = list.Where(num => num < 5); 
Console.WriteLine(query.Count()); 

list.RemoveAll(num => num < 4); 
Console.WriteLine(query.Count() 

這裏我們有一個數據列表,並計算小於5(它是4)的項目數。然後我們修改列表(根本不需要更改query)。我們重新查詢query,最終計爲1。

相關問題