針對 LINQ to SQL 斷開環境下更新實體的五種方案,進行 100/1000 次迭代基準測試,分析耗時、代碼複雜度、API 易用性,給出選型建議。
Products(含關聯 Categories、Suppliers、Order_Details)。CodeTimer(修正版支援 XP)。| 方案 | 核心思路 | 關鍵代碼片段 |
|---|---|---|
| 1. 重新賦值 | Get 原實體,逐屬性賦值新值 | old.Name = new.Name; ... db.SubmitChanges(); |
| 2. 禁用跟蹤 | ObjectTrackingEnabled=false,查詢返回非跟蹤實體,Attach 修改態 | db.ObjectTrackingEnabled=false; var p=db.Products...; db.Products.Attach(p, true); |
| 3. 移除關聯 | 查詢後手動置空 EntityRef/清空 EntitySet,斷開延遲加載器 | product.Category = null; // 或反射通用 Detach |
| 4. 委托延遲執行 | 將查詢邏輯與更新邏輯封裝在同一 DataContext 委托中 | Update(p => p.ID==1, p => { p.Name="New"; }); |
| 5. 手寫 SQL | 拼接 UPDATE 語句,僅更新髒列 | db.ExecuteCommand("UPDATE ... WHERE ID={0}", id); |
方案1 重新賦值(反射) : ~3.2s 最慢
方案1 重新賦值(手工) : ~2.8s 仍慢
方案2 禁用跟蹤 : ~1.1s 最快
方案3 移除關聯(反射) : ~1.3s
方案4 委托延遲 : ~1.2s
方案4 改良版(Action) : ~1.0s 略快於方案2
方案5 手寫 SQL : 未量化,框架耦合高
DataLoadOptions 載入關聯,稍繁瑣;方案 4 委托語法對初級開發者有門檻。// 簡單場景:委托一步到位
public void UpdateProduct(int id, Action<Product> updater) { ... }
// 複雜場景:Get + 手工修改 + Attach 更新
public Product GetProduct(int id) { ... }
public void UpdateProduct(Product product) { ... }
根據業務複雜度提供不同重載,兼顧性能、可讀性與靈活性。