Entity Framework Core的坑:Skip/Take放在Select以前形成Include的實體全表查詢

今天將一個遷移至 ASP.NET Core 的項目放到一臺 Linux 服務器上試運行。站點啓動後,瀏覽器打開一個頁面一直處於等待狀態。接着奇怪的事情發生了,整個 Linux 服務器響應緩慢,ssh命令行輸入都一頓一頓的,過了一會,直接中止響應,down機了,必須強制重啓服務器才行。再啓動站點,再訪問,問題依舊。換一臺服務器,down機依然。git

排查時在日誌中發現了這樣的報警:github

warn: Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory[8]
The LINQ expression 'xxx' could not be translated and will be evaluated locally. 

而後用 SQL Profiler 跟蹤了一下 EF Core 生成的 SQL 語句,發現了一條全表查詢的SQL語句,而這張表有80多萬條數據。罪魁禍首就是它,在內存中加載80多萬條數據進行查詢,結果把只有1核1G的Linux服務器搞掛了。數據庫

這個項目以前用的是基於 .NET Framework 的 Entity Framework ,並無出現這個問題。換成 Entity Framewor Core 怎麼就變卦了呢?express

後來在GitHub上發現了線索 —— The LINQ expression could not be translated and will be evaluated locally wrong warning瀏覽器

If possible, you should always try to put Skip/Take/Distinct as the last operation when using EF Core (at least until we address the current limitations).

在咱們這個項目中的確存在將 Skip/Take 放在 Select 以前的 LINQ 查詢代碼,修改以後問題立馬解決。而發生全表查詢的數據庫表所對應的實體,是在 LINQ 中 Include 進來的(Eager loading)。服務器

這是目前版本的 EF Core 的一個坑,使用時需注意。建議使用 EF Core 時,必定要看日誌中 EF Core 的報警信息。 ssh

相關文章
相關標籤/搜索