在我的應用程序(EF6 + SQL Server)中,我動態創建EF查詢以啓用豐富的搜索功能。與原始SQL執行時間相比,實體框架的性能開銷是多少?
這些查詢是通過鏈接一堆Where()謂詞並將結果使用少量聚合投影到已知的CLR類型中來創建的。在所有情況下,EF生成一個返回少量結果(大約10)的單個SQL查詢。
使用SQL事件探查器我可以看到,這些生成的查詢執行時間由數據庫執行幾毫秒。但是,除非查詢非常簡單,否則總執行時間(從我的代碼調用ToList()或Count())在幾百毫秒內!該代碼構建在發佈模式下,並且未經調試器測試。
任何人都可以給我任何提示什麼可能是我的方法錯了嗎?與原始SQL執行時間相比,EF的開銷是否有可能在時間上是兩個數量級?
編輯:
這些是我使用的篩選結果集的一些代碼樣品:
if (p.PriceMin != null)
query = query.Where(a => a.Terms.Any(t => t.Price >= p.PriceMin.Value));
if (p.StartDate != null && p.EndDate != null)
query = query.Where(a => a.Terms.Any(t => t.Date >= p.StartDate.Value && t.Date <= p.EndDate.Value));
if (p.DurationMin != null)
query = query.Where(a => a.Itinerary.OfType<DayElement>().Count() > p.DurationMin.Value - 2);
if (p.Locations != null && p.Locations.Count > 0)
{
var locs = p.Locations.Select(l => new Nullable<int>(l)).ToList();
query = query.Where(a => a.Itinerary.OfType<MoveToElement>().Any(e => locs.Contains(e.LocationId)) ||
a.Itinerary.OfType<StartElement>().Any(e => locs.Contains(e.LocationId)) ||
a.Itinerary.OfType<EndElement>().Any(e => locs.Contains(e.LocationId)));
}
然後我命令的結果是這樣的:
if (p.OrderById)
query = query.OrderBy(a => a.Id);
else if (p.OrderByPrice)
query = query.OrderByDescending(a => a.Terms.Average(t => t.Price));
的執行時間大致相同,如果我試圖連續多次執行相同的查詢(使用相同的DbContext調用多個query.Count()),所以我想在這種情況下,EF的查詢生成是非常有效的ient。看起來其他東西是瓶頸......
我在這裏看到了同樣的事情。我使用原始SQL查詢('Database.SqlQuery <>'),幾乎總是隻返回一行。 – Cameron
@Cameron你有沒有想過你的情況是什麼問題? –
不,對不起。我懷疑EF的開銷很高。我最終拋棄了EntityFramework而轉而使用Dapper(我極力推薦它)。我曾經使用過的最好的ORM(缺乏更好的術語)。儘管如此,原始SQL仍然太慢了(儘管現在瓶頸是服務器而不是客戶端),並且我最終放棄了SQL Server for SQLite(這很好,除非你有高流量的數據),然後最終拋棄對於我自己編寫的專用嵌入式SQL引擎。 – Cameron