Entity Framework Core 關聯資料讀取示範

假設使用 Entity Framework Core 8 , User 和 Employee 為一對一關聯 ,DbContext 如下:
    
public partial class ApplicationDbContext : DbContext
{
    public virtual DbSet<Employee> Employees { get; set; }
    public new virtual DbSet<User> Users { get; set; }
}
    

在查詢 Users 時可以這樣查詢:
    
var user = _dbContext.Users
    .FirstOrDefault(x => x.UserName == "ruyut");
    

此時雖然可以存取關聯的 Employee,但是 Employee 會是空,因為並沒有從資料庫中查詢該資料。

預先載入 Eager loading

想要一併取得 Employee 這個關聯資料表的內容可以使用預先載入,在查詢資料時一併讀取:
    
var user = _dbContext.Users
    .Include(user => user.Employee)
    .FirstOrDefault(x => x.UserName == "ruyut");
    

其中的資料庫語法會使用 LEFT JOIN 將兩個資料表的所有欄位一起查詢出來。

假設 Employee 資料表與 DepartmentEmployees 資料表關聯,還可以使用 ThenInclude 繼續查詢:
    
var user = _dbContext.Users
    .Include(user => user.Employee)
    .ThenInclude(x => x.DepartmentEmployees)
    .FirstOrDefault(x => x.UserName == "ruyut");
    

但是實際的 SQL 語法會在原本的語法中繼續 LEFT JOIN DepartmentEmployees 資料表,一不小心很可能導致查詢結果過多。

這種情況最好使用 select 只指定需要的欄位,就可以避免資料過多引發的效能問題:
    
var user = _dbContext.Users
    .Include(user => user.Employee)
    .Select(x => new
    {
        x.Id,
        x.UserName,
        x.Employee.DisplayName,
    })
    .FirstOrDefault();
    

實際 SQL 語法:
    
SELECT TOP(1) [u].[Id], [u].[UserName], [e].[DisplayName]
FROM [Users] AS [u]
LEFT JOIN [Employee] AS [e] ON [u].[Id] = [e].[UserId]
    

顯示載入 Explicit loading

假設在查詢完 Users 後,在後面需要存取關聯的 Employee 資料表可以怎麼做?
    
var user = _dbContext.Users
    .FirstOrDefault(x => x.UserName == "ruyut");
    

可以使用顯示載入:
    
_dbContext.Entry(user).Reference(x => x.Employee).Load();
    

在上方的程式碼執行會直接執行 SQL 語法查詢關聯的 Employee 資料表。

參考資料:
Microsoft.Learn - Eager Loading of Related Data

留言

張貼留言

如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com