LINQ (Language Integrated Query) 主打查詢優雅,但更新機制預設採用完整欄位樂觀平行存取:
SELECT 取得所有欄位。SubmitChanges() 產生 UPDATE,WHERE 條件包含所有原始欄位值。-- 步驟 1:查詢 (全欄位)
SELECT UserId, UserName, FirstName, LastName, CreateTime
FROM Users WHERE UserId = @p0
-- 步驟 2:更新 (WHERE 含所有原始值)
UPDATE Users SET UserName = @p1
WHERE UserId = @p0 AND UserName = @p2 AND FirstName = @p3 AND LastName = @p4 AND CreateTime = @p5
Views = Views + 1) 兩次讀寫間若有其他更新,WHERE 條件不符導致 ChangeConflictException,更新失敗。微軟稱此為 "by design",為防止資料被他人修改後覆蓋。
| 多載 | 程式碼 | 結果 |
|---|---|---|
| Attach(entity) | ctx.Users.Attach(newUser); | 無任何 SQL 產生,無效。 |
| Attach(entity, original) | ctx.Users.Attach(newUser, original); | 拋出 "Cannot add an entity with a key that is already in use." |
| Attach(entity, true) | ctx.Users.Attach(newUser, true); | 需實體宣告 Version 成員 (Timestamp) 或關閉 UpdateCheck。 |
RowVersion (Timestamp) 欄位,實體標記 [Column(IsVersion=true)]。[Column(UpdateCheck=UpdateCheck.Never)](但重新產生 DBML 會遺失,需手動維護)。缺點:WHERE 條件仍含 Timestamp,且 DBML 維護麻煩(VS 此版本無「更新模型」功能,需刪除重拖或用 SQLMetal)。
LINQ to SQL 查詢強大,但更新機制在高併發、大表、計數器場景下表現不佳。建議: