我正在嘗試使用System.Transactions(TransactionScope)來協調一組進程,每個進程都執行一些數據庫工作。最終,所有進程都需要通過一個父進程進行原子級回滾或回滾。不幸的是,迄今爲止我沒有嘗試過。跨進程使用事務
我的基本策略是在父進程中將TransactionScope保存到文件中,然後調用加載文件的子進程,在自己的TransactionScope中使用事務並返回到父進程。
但這不適用於我。當我從調用第一個孩子回來時,我有時會看到父交易已被標記爲中止。試圖克隆它然後拋出TransactionAbortedException。
當第二個孩子試圖反序列化事務時,我也看到異常,我得到一個TransactionException代碼0x8004d00e。
我想要做的是TransactionScope across AppDomains and processes和http://blogs.microsoft.co.il/blogs/sasha/archive/2010/04/30/propagating-a-transaction-across-appdomains.aspx中描述的內容。無論如何,沒有運氣。
這裏有一些事情我都試過了,沒有成功:
- 從加載交易
- 創建通過DependentClone父進程DependentTransaction()創建通過DependentClone子進程中的一個DependentTransaction() ,節省了 交易文件
- 創建克隆()在父進程,節省了 交易文件
- 保存我們在交易前前荷蘭國際集團系列化
- 保存使用 TransactionInterop.GetTransactionFromTransmitterPropagationToken()交易
- 明確地打開父母的 的TransactionScope前連接
- 明確爭取母公司內部交易
- 明確爭取孩子裏面的交易
- 完成/未完成父母的範圍
- 完成/未完成對子女的範圍
- 父
明確創建CommittableTransaction這裏有一個例外消息:
System.Transactions.TransactionException:該事務已或隱式地提交或中止。 ---> System.Runtime.InteropServices.COMException:該事務已或隱式地提交或(從HRESULT異常:0x8004D00E)中止
,而其他(使用DependentClone時()):
系統.Transactions.TransactionAbortedException:事務已中止。 at System.Transactions.TransactionStatePromotedAborted.CreateBlockingClone( ternalTransaction tx) at System.Transactions.DependentTransaction ..構造函數(ISOLEVEL的IsolationLevel,在 ternalTransaction internalTransaction,布爾阻塞) 在System.Transactions.Transaction.DependentClone(DependentCloneOption cloneO ption)
任何想法我做錯了嗎?我已經嘗試了很多這個沒有任何運氣的排列組合。
下面是一些代碼(不試圖證明上述所有變體):
// one variant I have tried is to create a CommittableTransaction
// and pass that in the scope below
using (TransactionScope scope = new TransactionScope())
{
// optionally, do some parent-level EF work
// invoke child operations in other processes
DoChildOperation_OutOfProc(1, Transaction.Current);
DoChildOperation_OutOfProc(2, Transaction.Current);
scope.Complete();
}
// in the variant where I created a CommittableTransaction,
// I committed it here
...
private static void DoChildOperation_OutOfProc(int id, Transaction transaction)
{
string tranFile = string.Format("ChildTran_{0}.txt", id);
SaveTransactionToFile(transaction, tranFile);
Process process = new Process();
process.StartInfo = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName.Replace(".vshost", string.Empty),
string.Format("-CHILDID={0} -TRANFILE={1}", id, tranFile));
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
}
private static void SaveTransactionToFile(Transaction transaction, string tranFile)
{
byte[] transactionBytes =
TransactionInterop.GetTransmitterPropagationToken(transaction);
string tranFileContents = Convert.ToBase64String(transactionBytes);
File.WriteAllText(tranFile, tranFileContents);
}
private static Transaction LoadTransactionFromFile(string tranFile)
{
string tranFileContents = File.ReadAllText(tranFile);
File.Delete(tranFile);
byte[] tranBytes = Convert.FromBase64String(tranFileContents);
Transaction tran =
TransactionInterop.GetTransactionFromTransmitterPropagationToken(tranBytes);
return tran;
}
// the child instance of the app runs this after decoding the arguments
// from DoChildOperation_OutOfProc() and loading the transaction out of the file
private static void DoChildOperation(int id, Transaction childTransaction)
{
// in one variant, I call
// childTransaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete)
// and then use that inside the TransactionScope
using (TransactionScope scope = new TransactionScope(childTransaction))
{
// do EF work and call SaveChanges()
scope.Complete();
}
// if I created a dependent clone, call Complete() here on it
這真的很好,你已經解釋了你遇到的問題/錯誤..但是你能否顯示完整的代碼塊正在執行事務代碼..? – MethodMan
我已經添加了一些代碼,有點消毒,但希望它更清楚。 – Todd
這看起來很毛茸茸。任何原因你不能將工作分成多個交易,並在必要時使用補償來回滾> –