gpt4 book ai didi

c# - 跨进程使用事务

转载 作者:太空宇宙 更新时间:2023-11-03 13:51:29 26 4
gpt4 key购买 nike

我正在尝试使用 System.Transactions (TransactionScope) 来协调一组进程,每个进程都执行一些数据库工作。最终,所有进程都需要通过一个父进程以原子方式提交或回滚。不幸的是,到目前为止我没有尝试过。

我的基本策略是父进程中的 TransactionScope,将其保存到文件,并调用子进程,子进程加载文件,在其自己的 TransactionScope 中使用事务,然后返回给父进程。

但这对我不起作用。当我调用第一个 child 回来时,我有时会看到父事务已被标记为已中止。尝试克隆它然后抛出 TransactionAbortedException。

当第二个 child 尝试反序列化事务时,我也看到了异常,我得到了代码为 0x8004d00e 的 TransactionException。

我正在尝试执行 TransactionScope across AppDomains and processes 中描述的操作, 和 http://blogs.microsoft.co.il/blogs/sasha/archive/2010/04/30/propagating-a-transaction-across-appdomains.aspx .无论如何,运气不好。

以下是我尝试过的一些方法,但没有成功:

  1. 从加载的事务中通过 DependentClone() 在子进程中创建 DependentTransaction
  2. 在保存之前,在父进程中通过 DependentClone() 创建一个 DependentTransaction文件交易
  3. 在保存之前在父进程中创建一个 Clone()文件交易
  4. 使用序列化保存交易
  5. 保存交易使用TransactionInterop.GetTransactionFromTransmitterPropagationToken()
  6. 在父级之前显式打开连接事务范围
  7. 在父级内部明确征集事务
  8. 在 child 内部明确征集交易
  9. 完成/未完成父级范围
  10. 完成/未完成 child 的范围
  11. 在父级中显式创建 CommittableTransaction

这是一条异常消息:

System.Transactions.TransactionException:事务已经隐式或显式提交或中止。 ---> System.Runtime.InteropServices.COMException:事务已隐式或显式提交或中止(HRESULT 异常:0x8004D00E)

另一个(使用 DependentClone() 时):

System.Transactions.TransactionAbortedException:事务已中止。 在 System.Transactions.TransactionStatePromotedAborted.CreateBlockingClone(在ternalTransaction tx) 在 System.Transactions.DependentTransaction..ctor(隔离级别 isoLevel,在ternalTransaction internalTransaction, bool 阻塞) 在 System.Transactions.Transaction.DependentClone(DependentCloneOption cloneO选项)

知道我做错了什么吗?我已经尝试了很多这种排列,但没有任何运气。

下面是一些代码(不尝试演示上述所有变体):

        // 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

最佳答案

好的,关键似乎是您可以在父级中使用 TransactionScope,但不能在子级中使用。对于 child ,我打开 EF 连接,使用传递的事务调用 connection.EnlistTransaction(),然后执行 EF SaveChanges() 或 transaction.Rollback() 但不提交(Transaction 类不提供此功能)。这样做,我似乎得到了想要的行为。

我理解上的差距实际上是事务是否嵌套(就像您在 SQL Server 中所做的那样)。看起来它真的不是;这是同一笔交易。注意:即使您在子级中使用 Transaction.DependentClone() 创建 DependentTransaction,如果将其放入 TransactionScope 中,您仍然会失败。

事实证明这有点不幸,因为这意味着如果您的进程是父进程,您可以使用 TransactionScope,但如果它是子进程,则不能。

关于c# - 跨进程使用事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13574245/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com