2016-01-01 44 views
1

我正在使用實體框架6來檢索具有多個導航屬性的實體,以嵌套深實體。我正面臨着巨大的性能影響,這已經被實體框架的請求所記錄下來。我在最深的實體(Geocoordinate)中擁有數百條記錄,檢索Session實體需要8秒(我不到1秒)。使用實體框架檢索許多嵌套實體的性能下降

這裏是日誌的要點樣本: https://gist.github.com/bbougot/837419c682a75d4741a5

這裏是我的代碼:

 using (var context = new ModelContainer()) 
     { 
      context.Database.Log = msg => Trace.WriteLine(msg); 
      var session= await 
       context.SessionSet.FirstOrDefaultAsync(a => a.Identifier == sessionIdentifier); 
      var result = await Json(session).ExecuteAsync(new CancellationToken()); 
      return ResponseMessage(result); 
     } 

我取回我的模型的紅色實體(注意之間的唯一一個一對多的關係路線和Geoposition):

mode

(鏈接到大尺寸圖像:http://i.imgur.com/adRw6br.jpg?1

我試過禁用懶加載和使用包括加載我的實體,但它更糟糕,我已經達到了SQL Server超時。

+0

你確定這是EF的問題嗎?我的意思是如果你運行類似的TSQL查詢,它運行速度更快嗎? – Rahul

+0

不,它是差不多的...我認爲我的模型沒有真正優化。我會簡化一些關係,然後表現應該更好。 – Ben

回答

2

實體需要這麼長時間才能加載的原因是您遭受了經典的選擇N + 1問題。

因爲您似乎已經知道實體框架默認情況下通過在它們周圍創建動態代理對象來延遲加載所有導航屬性。如果它檢測到代理已被訪問(即您遵循導航屬性),那麼它會向數據庫發出查詢以實際關閉並獲取數據。造成性能影響的原因是,每個執行的數據庫查詢都有一定的開銷(例如數據庫服務器的延遲),因此最好的選擇是執行一個查詢,將所有的您需要的數據,而不是單獨的查詢每個單獨的實體。

當涉及到集合屬性(例如您Route -> Geoposition關係),然後事情變得更糟,因爲實體框架將生成集合中的每個項單獨的選擇。這就是爲什麼你在日誌中看到如此多的數百個查詢。

我試過禁用延遲加載並使用Include加載我的 實體,但更糟的是,我已經達到SQL Server超時。

使用Include方法是將引導屬性熱切加載爲初始查詢的一部分的正確方法。如果在相關導航屬性之後仍然發現查詢執行時間太長,則應查看查詢的執行計劃以查看性能問題的位置。發佈另一個問題,如果你需要幫助分析它。

+1

這解決了我的問題,謝謝!急切地加載有問題的實體是關鍵。 – Ben