Linq to SQL 預設採 樂觀平行存取:更新時比對原始值,若資料庫已被修改則拋出 ChangeConflictException。可在 [Column] 設定 UpdateCheck=UpdateCheck.Never 忽略特定欄位檢查。
try {
ctx.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException) {
foreach (var cc in ctx.ChangeConflicts) {
var p = (Product)cc.Object;
// 1. OverwriteCurrentValues:放棄本地修改,以資料庫值為準
// cc.Resolve(RefreshMode.OverwriteCurrentValues);
// 2. KeepCurrentValues:放棄資料庫修改,以本地值為準
// cc.Resolve(RefreshMode.KeepCurrentValues);
// 3. KeepChanges (預設):合併非衝突欄位,衝突欄位以本地值為準
cc.Resolve(RefreshMode.KeepChanges);
}
ctx.SubmitChanges();
}
foreach (var cc in ctx.ChangeConflicts) {
foreach (var mc in cc.MemberConflicts) {
if (mc.Member.Name == "UnitsInStock") mc.Resolve(RefreshMode.KeepCurrentValues);
else if (mc.Member.Name == "UnitPrice") mc.Resolve(RefreshMode.OverwriteCurrentValues);
else mc.Resolve(RefreshMode.KeepChanges);
}
}
ContinueOnConflict:嘗試處理所有衝突,最後統一解決。FailOnFirstConflict:遇到第一個衝突即停止,不繼續處理後續。SubmitChanges() 內部自動開啟交易,任一操作失敗整批回滾。
if (ctx.Connection.State != ConnectionState.Open) ctx.Connection.Open();
var tran = ctx.Connection.BeginTransaction();
ctx.Transaction = tran;
try {
CreateCustomer(new Customer { CustomerID="abcdf", CompanyName="zhuye" });
CreateCustomer(new Customer { CustomerID="abcde", CompanyName="zhuye" }); // 重複 PK 失敗
tran.Commit();
} catch { tran.Rollback(); }
using (var scope = new TransactionScope()) {
CreateCustomer(new Customer { CustomerID="abcdf", CompanyName="zhuye" });
CreateCustomer(new Customer { CustomerID="abcde", CompanyName="zhuye" });
scope.Complete();
}
支援分散式交易,程式碼更簡潔。