2016-06-10 34 views
1

我一直在看一個當然筆者提到這裏,如果你有一些IQueryable的,說:迭代的IQueryable用foreach與調用ToList(),然後做的forEach - 性能

var someQuery = dbContext.Table.Where(x => x.Name == "Mark"); 

,然後嘗試使用forEach迭代someQuery的結果,它會保持數據庫連接處於打開狀態,直到整個forEach結束,並且很多初學者開發者犯了這個錯誤,並且在forEach中執行了大量邏輯。相反,她建議只在前臺調用toList(),然後在內存中收集forEach

雖然我找不到任何參考,但實體框架會保持數據庫處於打開狀態,直到forEach循環停止。我如何評估這是否真正的性能?

+0

我已經[發現了困難的方式](http://stackoverflow.com/a/22530381/261050) – Maarten

+0

是的,它會保持連接打開,直到它遇到.toL​​ist() –

+1

連接保持打開,直到枚舉'IQueryable'完成。這會發生在'foreach'循環結尾或調用'.ToList()'時。然而,不清楚的是,以這種或那種方式進行這種表演會有性能損失。確保數據庫連接長時間保持打開狀態肯定存在問題 - 您通常希望儘快釋放連接。 – Enigmativity

回答

3

適用於IQueryable<T>ToList()方法是一種擴展方法,您可以在System.core.dll中使用.NET反編譯器進行查看; 如果源是ICollection<T>,則方法複製「專用陣列」,否則它將執行源的foreach循環。

IQueryable<T>的實際執行是System.Data.Entity.Infrastructure.DbQuery<TResult>而且它不是ICollection<T>

因此,ToList()基本上使用foreach複製源。

現在,它取決於實現,但使用EF內核作爲示例,有一個Enumerator class,您可以看到在處理類時連接(IRelationalConnection)已關閉。 根據另一個answer和ms documentation,應儘快關閉連接以釋放連接並使其在連接池中可用。

爲每個唯一連接字符串創建一個連接池。創建池時,將創建多個連接對象並將其添加到池中,以滿足最小池大小要求。根據需要將連接添加到池中,直到指定的最大池大小(默認爲100)。連接在關閉或丟棄時釋放回池中。

因此,如果您正在執行復雜的操作或執行其他查詢或foreach內的其他任何內容,ToList是首選。