WCF 支援跨服務的分散式交易,基於兩階段提交協定 (Two-Phase Commit, 2PC),確保多個服務操作的原子性:要麼全成功,要麼全回滾。
[TransactionFlow(TransactionFlowOption.Mandatory)] 強制要求呼叫端傳入交易[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 在交易範圍內執行wsHttpBinding 設定 transactionFlow="true" 支援交易流動[ServiceContract]
public interface IHello {
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
void WriteHello(string name);
}
public class Hello : IHello {
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void WriteHello(string name) {
var ctx = new DBDataContext();
ctx.Items.InsertOnSubmit(new Item {
Title = $"Hello: {name}, TransactionId: {Transaction.Current.TransactionInformation.LocalIdentifier}",
CreatedTime = DateTime.Now
});
ctx.SubmitChanges();
}
}
[ServiceContract]
public interface IHi {
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
void WriteHi(string name);
}
public class Hi : IHi {
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void WriteHi(string name) {
if (DateTime.Now.Second % 2 == 0)
throw new Exception("為測試交易而拋出的異常");
var ctx = new DBDataContext();
ctx.Items.InsertOnSubmit(new Item {
Title = $"Hi: {name}, TransactionId: {Transaction.Current.TransactionInformation.LocalIdentifier}",
CreatedTime = DateTime.Now
});
ctx.SubmitChanges();
}
}
[ServiceContract]
public interface IResult {
[OperationContract] List<Item> GetResult();
}
public class Result : IResult {
public List<Item> GetResult() {
var ctx = new DBDataContext();
return ctx.Items.OrderByDescending(x => x.CreatedTime).ToList();
}
}
<bindings>
<wsHttpBinding>
<binding name="TransactionConfiguration" transactionFlow="true" />
</wsHttpBinding>
</bindings>
<services>
<service name="WCF.ServiceLib.Transaction.Hello" behaviorConfiguration="TransactionBehavior">
<endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHello" bindingConfiguration="TransactionConfiguration" />
</service>
<service name="WCF.ServiceLib.Transaction.Hi" behaviorConfiguration="TransactionBehavior">
<endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHi" bindingConfiguration="TransactionConfiguration" />
</service>
<service name="WCF.ServiceLib.Transaction.Result" behaviorConfiguration="TransactionBehavior">
<endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.Transaction.IResult" />
</service>
</services>
var proxyHello = new TransactionSvc.Hello.HelloClient();
var proxyHi = new TransactionSvc.Hi.HiClient();
var proxyResult = new TransactionSvc.Result.ResultClient();
var options = new TransactionOptions {
IsolationLevel = IsolationLevel.Serializable,
Timeout = TimeSpan.FromSeconds(30)
};
using (var ts = new TransactionScope(TransactionScopeOption.Required, options)) {
try {
proxyHello.WriteHello("webabcd");
proxyHello.Close();
proxyHi.WriteHi("webabcd"); // 可能拋出異常
proxyHi.Close();
ts.Complete(); // 兩階段提交:準備階段 -> 提交階段
lblErr.Text = "OK";
} catch (Exception ex) {
lblErr.Text = ex.ToString(); // 未呼叫 Complete,交易自動回滾
}
}
GridView1.DataSource = proxyResult.GetResult();
GridView1.DataBind();
| 選項 | 說明 |
|---|---|
| Mandatory | 強制要求呼叫端提供交易,否則拋出例外 |
| Allowed | 允許但不強制,有交易則加入,無則建立新交易 |
| NotAllowed | 禁止交易流動(預設值) |
WCF 分散式交易讓微服務架構也能擁有 ACID 保證,是金融、電商等強一致性場景的關鍵技術。