| 模式 | 觸發時機 | 適用場景 | 資料庫往返 |
|---|---|---|---|
| 延遲加載 (默認) | 訪問導航屬性時 | 不確定是否需要關聯數據 | 多次 (N+1 問題) |
| 預加載 LoadWith | 主查詢執行時 | 確定需要關聯數據 | 單次 (JOIN) |
| 關聯篩選 AssociateWith | 預加載時 | 只需關聯數據子集 | 單次 (帶 WHERE 的 JOIN) |
| 加載重寫 (分部方法) | 加載特定關聯時 | 自定義加載邏輯 (如存儲過程) | 可控 |
var custs = from c in db.Customers
where c.City == "Sao Paulo"
select c;
// 查詢尚未執行
foreach (var cust in custs) {
foreach (var ord in cust.Orders) { // 此處觸發新查詢
// ...
}
}
優點:按需查詢;缺點:遍歷集合時產生 N+1 次查詢。
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<Customer>(c => c.Orders);
db.LoadOptions = ds;
var custs = from c in db.Customers
where c.City == "Sao Paulo"
select c;
// 單次查詢使用 LEFT JOIN 同時獲取 Customers + Orders
DataLoadOptions ds = new DataLoadOptions();
ds.AssociateWith<Customer>(c => c.Orders.Where(o => o.ShipVia > 1));
db.LoadOptions = ds;
// 僅預加載 ShipVia > 1 的訂單,但生成多條 SQL (非單一 JOIN)
注意:AssociateWith 配合延遲加載時仍會產生多查詢;配合 LoadWith 可在單查詢中篩選。
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<Customer>(c => c.Orders);
ds.LoadWith<Order>(o => o.OrderDetails);
ds.AssociateWith<Order>(o => o.OrderDetails.OrderBy(od => od.Quantity));
db.LoadOptions = ds;
// 單次查詢獲取 Customer → Orders → OrderDetails,且明細按數量排序
// Category 分部類
partial class Category {
private IEnumerable<Product> LoadProducts(Category category) {
// 可調用存儲過程或自定義邏輯
return this.Products
.Where(p => p.CategoryID == category.CategoryID)
.Where(p => !p.Discontinued);
}
}
// 使用時
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<Category>(c => c.Products);
db.LoadOptions = ds;
// 加載 Category.Products 時自動調用上述 LoadProducts 方法
LoadWithLoadWith + AssociateWith