交易確保應用程式資料一致性:將多項作業視為單一工作單元,要么全成功要么全失敗。若中途失敗,系統需回到交易前的狀態。
XA 交易 (兩階段提交) 要求資源 (資料庫) 鎖定資料直到提交/回滾。若交易包含長時間人工作業 (如等待信用卡驗證),資料庫連接與鎖定將長時間佔用,嚴重影響並發與擴展性。網路環境下更不可行。
不鎖定資源,交易成功即提交;失敗時由應用程式執行「補償動作」抵銷已完成作業 (如已扣款則存回)。優點:資源無長時間鎖定、支援非交易資源 (Web 服務)。缺點:需自行撰寫補償邏輯,錯誤可能導致狀態更不一致。
使用交易活動需啟用兩項服務:
SqlWorkflowPersistenceService (活動標記 PersistOnClose)DefaultWorkflowTransactionService (負責交易啟動/提交)TransactionOptions 設定隔離等級 (預設 Serializable) 與逾時。ICompensatableActivity,提供補償處理常式。ThrowActivity 觸發補償。CompensateActivity 控制補償順序。CompensatableTransactionScope,將相關交易群組。CompensateActivity 指定補償特定子活動或全部。CompensatableTransactionScope 內。模擬自動櫃員機:存款使用 XA 交易 (TransactionScope),提款使用補償式交易 (CompensatableTransactionScope)。資料庫含帳號、PIN、餘額;預存程序強制在交易中執行 (檢查 @@TRANCOUNT)。
Create Woodgrove Database.sql 建立 Woodgrove (業務資料) 與 WorkflowStore (持久化) 兩個資料庫。App.config 連接字串。Workflow1.cs 設計工具,進入 DepositState → CmdPressed4 分支。TransactionScopeActivity 置於 MakeDeposit (CodeActivity) 上方。MakeDeposit 拖入 TransactionScope 內。


WithdrawState → CmdPressed5 分支。CompensatableTransactionScopeActivity 包裹 MakeWithdrawal。CodeActivity (CompensateWithdrawal):手動建立 SQL 交易呼叫 Deposit 預存程序存回提款金額。FailedActivity (錯誤訊息) 與 SetStateActivity (轉至 CompletedState)。
private void CompensateWithdrawal(object sender, EventArgs e)
{
string connString = ConfigurationManager.ConnectionStrings["BankingDatabase"].ConnectionString;
if (!String.IsNullOrEmpty(connString))
{
SqlConnection conn = null; SqlTransaction trans = null;
try
{
conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand("dbo.Deposit", conn) { CommandType = CommandType.StoredProcedure };
cmd.Parameters.Add(new SqlParameter("@AccountNo", SqlDbType.Int) { Value = _account });
cmd.Parameters.Add(new SqlParameter("@ThrowError", SqlDbType.SmallInt) { Value = 0 });
cmd.Parameters.Add(new SqlParameter("@Amount", SqlDbType.Money) { Value = CurrentMoneyValue });
SqlParameter outParm = new SqlParameter("@Balance", SqlDbType.Money) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(outParm);
conn.Open();
trans = conn.BeginTransaction();
cmd.Transaction = trans;
cmd.ExecuteNonQuery();
trans.Commit();
CurrentBalance = (decimal)outParm.Value;
}
catch { if (trans != null) trans.Rollback(); }
finally { if (conn != null) conn.Close(); }
}
}



MakeWithdrawal 實際成功扣款,但隨後觸發補償存回,最終餘額不變。CompensateActivity 可在補償/取消/錯誤處理常式中指定 TargetActivityName,實現選擇性或自訂順序補償。CompensatableSequence 補償處理常式中呼叫 CompensateActivity 指定父活動,所有已成功的子活動皆會補償。WF 提供兩種交易模型:TransactionScope 適合短時資料庫操作;CompensatableTransactionScope 適合長時間流程或非交易資源。補償邏輯需謹慎設計,確保能正確逆向已完成作業。透過 CompensatableSequence 與 CompensateActivity 可精確控制複雜業務流程的補償行為。