今天將一個遷移至 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