首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

LINQ to SQL 查詢與新增實戰:Identity Cache 與延遲載入機制解析

     編輯:關於.NET

本文以 Northwind 資料庫 Customers、Orders 表為例,實戰演示 LINQ to SQL 的新增、查詢操作,並深入解析 **Identity Cache (身分識別快取)** 與 **延遲載入** 兩大核心機制對開發行為的影響。

環境建置

  1. 專案新增 LINQ to SQL Classes → Northwind.dbml
  2. 伺服器總管連接 Northwind → 將 Customers、Orders 拖曳至設計介面
  3. 自動產生 NorthwindDataContext、Customer、Order 實體類別

基本新增與查詢流程


var ctx = new NorthwindDataContext();

// 新增客戶
var c = new Customer { CustomerID = "Test1", CompanyName = "Test Company1" };
ctx.Customers.InsertOnSubmit(c);
ctx.SubmitChanges(); // 發送 INSERT 陳述式

// 查詢剛新增的客戶
var c1 = ctx.Customers.Single(c => c.CustomerID == "Test1");
Console.WriteLine($"{c1.CustomerID} {c1.CompanyName}");
// 輸出: Test1 Test Company1

Identity Cache 實測:同一 DataContext 內查詢不觸發 SQL


var ctx = new NorthwindDataContext();
var c = new Customer { CustomerID = "Test2", CompanyName = "Test Company2" };
ctx.Customers.InsertOnSubmit(c);
ctx.SubmitChanges(); // 執行 INSERT

// 同一 DataContext 再次查詢主鍵
var c1 = ctx.Customers.Single(ct => ct.CustomerID == "Test2");
Console.WriteLine($"{c1.CustomerID} {c1.CompanyName}"); // 正確輸出

SQL Profiler 觀察結果

  • 僅出現 **1 條 INSERT** 陳述式
  • **無 SELECT 陳述式** 產生

機制解析

  1. SubmitChanges() 後,DataContext 將新實體放入 **Identity Cache** (內部 Dictionary<object, object>,Key 為主鍵值)。
  2. 後續 Single(pk) 查詢時,DataContext 偵測到:查詢條件 **僅包含主鍵** 且 **目標型別為實體型別** → 直接從快取回傳實體參考,**完全略過資料庫查詢**。
  3. 此機制保證 **同一 DataContext 內,同一主鍵永遠回傳同一實體實例**,維護物件圖一致性。

失效條件 (會觸發真實 SQL 查詢)

  • 查詢條件 **包含非主鍵欄位** (如 Where(c => c.CompanyName == "X"))
  • 使用 **不同 DataContext 實例** 查詢
  • 關閉追蹤:ctx.ObjectTrackingEnabled = false
  • 呼叫 ctx.Refresh(RefreshMode.OverwriteCurrentValues, entity) 強制重新載入

一對多關聯查詢:延遲載入實測


var c = ctx.Customers.Single(ct => ct.CompanyName == "Test Company1");

// 此時尚未載入 Orders
foreach (var order in c.Orders) // 存取導航屬性 Orders 時
{
    Console.WriteLine(order);   // 才發送 SELECT * FROM Orders WHERE CustomerID = 'Test1'
}

SQL Profiler 驗證

  • 查詢 Customer 時:**無 Orders 關聯查詢**
  • 存取 c.Orders 時:**才發送 Orders 查詢**
這與 Hibernate lazy="true" 機制相同:關聯集合預設延遲載入,首次存取才觸發 SQL。

Delay Loaded (延遲載入欄位) 技巧

針對大型欄位 (圖片 varbinary(max)、長文本 nvarchar(max)),可在 DBML 設計器屬性視窗將欄位 Delay Loaded 設為 True:

  • 實體載入時 **不包含該欄位資料**
  • 首次存取該屬性時,**單獨發送 SELECT 欄位 FROM 表 WHERE PK**
  • 大幅降低列表查詢、序列化時的記憶體與網路開銷

DBML 設計器 Delay Loaded 設定

總結

機制觸發條件效果控制方式
Identity Cache同一 DataContext + 主鍵查詢回傳快取實體,零 SQLObjectTrackingEnabled、Refresh()
延遲載入 (關聯)存取導航屬性 (EntitySet/EntityRef)按需載入關聯資料DBML 關聯屬性、DataLoadOptions.LoadWith 預先載入
Delay Loaded (欄位)存取標記為 Delay Loaded 的屬性按需載入大型欄位DBML 欄位屬性 Delay Loaded = True

理解這三大機制,能精準預測 LINQ to SQL 的 SQL 產生行為,避免 N+1 查詢問題、記憶體暴漲與非預期的資料庫往返,寫出高效能資料存取程式碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved