假設使用 Entity Framework Core 8 , User 和 Employee 為一對一關聯 ,DbContext 如下:
在查詢 Users 時可以這樣查詢:
此時雖然可以存取關聯的 Employee,但是 Employee 會是空,因為並沒有從資料庫中查詢該資料。
其中的資料庫語法會使用 LEFT JOIN 將兩個資料表的所有欄位一起查詢出來。
假設 Employee 資料表與 DepartmentEmployees 資料表關聯,還可以使用 ThenInclude 繼續查詢:
但是實際的 SQL 語法會在原本的語法中繼續 LEFT JOIN DepartmentEmployees 資料表,一不小心很可能導致查詢結果過多。
這種情況最好使用 select 只指定需要的欄位,就可以避免資料過多引發的效能問題:
實際 SQL 語法:
可以使用顯示載入:
在上方的程式碼執行會直接執行 SQL 語法查詢關聯的 Employee 資料表。
參考資料:
Microsoft.Learn - Eager Loading of Related Data
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
感謝教學~
回覆刪除