Entity Framework中IQueryable, IEnumerable, IList的区别(转自网络)
?
使用工具追蹤EF生成的SQL
使用Entity Framework等ORM框架的時候,SQL對于使用者來說是透明的,往往很多人也不關心ORM所生成的SQL,然而系統(tǒng)出現(xiàn)性能問題的時候就必須關注生成的SQL以發(fā)現(xiàn)問題所在。
使用過Toplink的朋友知道很只要設置日志打印級別=FINE就可以配置使之生成的SQL在服務器中打印出來,Entiry Framework沒有那么幸運,在以前要檢測生成SQL的唯一方法是SQL Server Profiler,但使用起來并不方便,結(jié)果也不能自動保存到文件中。
Tracing and Caching Provider Wrappers for Entity Framework是Entity Framework Team新推出的開源SQL追蹤和二級緩存的解決方案。原理是在負責執(zhí)行具體SQL語句的data provider(SqlClient或者其他Client)之上插入了一層WrappingProvider,用于監(jiān)控 DbCommand.ExecuteReader(), ExecuteScalar() and ExecuteNonQuery(),將Sql命令輸出到指定介質(zhì)或者將查詢結(jié)果緩存起來以重用。
使用方法很簡單,下載源代碼編譯后將dll添加到項目中,新加一個類WrappedNorthWindEntities繼承原有的Entities即可,詳見源代碼中的示例。
測試IQueryable, IEnumerable, IList的區(qū)別
下面我們使用EF Wrapper來監(jiān)測Entify Framework中IQueryable, IEnumerable和IList所生成的SQL。
TestIQueryableprivate static void TestIQueryable() {using (var ctx = new WrappedNorthWindEntities()){IQueryable<Product> expression = ctx.Products.Take(5);IQueryable<Product> products = expression.Take(2); // A 不執(zhí)行SQLConsole.WriteLine(products.Count()); // B SELECT COUNT(1) FROM ( SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] ))Console.WriteLine(products.Count()); // C SELECT COUNT(1) FROM ( SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] ))foreach (Product p in products) // D SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] {Console.WriteLine(p.ProductName);}foreach (Product p in products) // E SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] ) {Console.WriteLine(p.ProductName);}} } TestIEnumerableprivate static void TestIEnumerable() {using (var ctx = new WrappedNorthWindEntities()){IEnumerable<Product> expression = ctx.Products.Take(5).AsEnumerable();IEnumerable<Product> products = expression.Take(2); // A 不執(zhí)行SQLConsole.WriteLine(products.Count()); // B SELECT TOP (5) * FROM [dbo].[Products]Console.WriteLine(products.Count()); // C SELECT TOP (5) * FROM [dbo].[Products]foreach (Product p in products) // D SELECT TOP (5) * FROM [dbo].[Products] {Console.WriteLine(p.ProductName);}foreach (Product p in products) // E SELECT TOP (5) * FROM [dbo].[Products] {Console.WriteLine(p.ProductName);}} } TestIListprivate static void TestIList() {using (var ctx = new WrappedNorthWindEntities()){var expression = ctx.Products.Take(5);IList<Product> products = expression.Take(2).ToList(); // A SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] Console.WriteLine(products.Count()); // B 不執(zhí)行SQLConsole.WriteLine(products.Count()); // C 不執(zhí)行SQLforeach (Product p in products) // D 不執(zhí)行SQL {Console.WriteLine(p.ProductName);}foreach (Product p in products) // E 不執(zhí)行SQL {Console.WriteLine(p.ProductName);}} }測試結(jié)果
以下是一個IQueryable引發(fā)數(shù)據(jù)不一致性的例子:記錄總數(shù)和記錄詳情兩者本應一致,但由于IQueryable前后兩次讀取數(shù)據(jù)庫,結(jié)果是現(xiàn)實有10條記錄,卻輸出11條詳情。
?
IQueryable Data InconsistancyIQueryable<Product> products = ctx.Products.All();//開始的時候數(shù)據(jù)庫product表中有10條記錄, count = 10int count = products.Count();Console.WriteLine("Count of products:"+count); //此時另一進程添加一個產(chǎn)品進數(shù)據(jù)庫//會重新讀取數(shù)據(jù)庫并輸出11個產(chǎn)品名稱foreach (Product p in products) {Console.WriteLine(p.ProductName); }結(jié)論
基于性能和數(shù)據(jù)一致性這兩點,我們使用IQueryable時必須謹慎,而在大多數(shù)情況下我們應使用IList。
- 當你打算馬上使用查詢后的結(jié)果(比如循環(huán)作邏輯處理或者填充到一個table/grid中),并且你不介意該查詢會即時執(zhí)行,使用ToList()
- 當你希望查詢后的結(jié)果可以供調(diào)用者(Consummer)作后續(xù)查詢(比如這是一個"GetAll"的方法),或者你希望該查詢延時執(zhí)行,使用AsQueryable()
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/caoheyang911016/p/3178886.html
總結(jié)
以上是生活随笔為你收集整理的Entity Framework中IQueryable, IEnumerable, IList的区别(转自网络)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STP、RSTP、MSTP
- 下一篇: 将今天写进历史,即可得出现在的世界是数字