TransactionScope 问题 - 如何防止 DTC 参与其中?

发布于 2024-08-15 00:21:00 字数 1189 浏览 8 评论 0原文

(我知道围绕 DTC 和促进交易的情况对于我们这些不了解情况的人来说可能有点神秘,但让我向您展示我的公司是如何做事的,以及您是否可以告诉我为什么 DTC 参与其中,如果可能的话,我能做些什么来避免它,我将不胜感激。)

我的代码在 ASP.Net Web 服务器上运行。我们有一个数据库,SQL 2008。

我们的数据访问代码看起来像这样——我们有一个数据访问层,它使用 SQLConnections 和 SQLCommands 的包装器对象。典型用法如下所示:

void method1()
{
    objDataObject = new DataAccessLayer();
    objDataObject.Connection = SomeConnectionMethod();
    SqlCommand objCommand = DataAccessUtils.CreateCommand(SomeStoredProc);

//create some SqlParameters, add them to the objCommand, etc....

objDataObject.BeginTransaction(IsolationLevel.ReadCommitted);
objDataObject.ExecuteNonQuery(objCommand);
objDataObject.CommitTransaction();
objDataObject.CloseConnection();
}

确实,一个围绕 SqlClient、SqlConnection 等的非常薄包装器。我想在事务中运行多个存储过程,而包装器类不允许我访问 SqlTransaction所以我无法将它从一个组件传递到下一个组件。这导致我使用 TransactionScope:

using (TransactionScope tx1 = new TransactionScope(TransactionScope.RequiresNew))
{
  method1();
  method2();
  method3();
  tx1.Complete();
}

当我这样做时,DTC 会介入,不幸的是我们的网络服务器没有在 MSDTC 设置中启用“允许远程客户端”——要让 IT 允许这样做将是一场斗争。

我很想避免 DTC 参与其中,但我能做到吗?我可以省略methods1-3() 中的事务调用,而只让TransactionScope 解决所有问题吗?

(I know the circumstances surrounding the DTC and promoting a transaction can be a bit mysterious to those of us not in the know, but let me show you how my company is doing things, and if you can tell me why the DTC is getting involved, and if possible, what I can do to avoid it, I'd be grateful.)

I have code running on an ASP.Net webserver. We have one database, SQL 2008.

Our data access code looks something like this-- We have a data access layer that uses a wrapper object for SQLConnections and SQLCommands. Typical use looks like this:

void method1()
{
    objDataObject = new DataAccessLayer();
    objDataObject.Connection = SomeConnectionMethod();
    SqlCommand objCommand = DataAccessUtils.CreateCommand(SomeStoredProc);

//create some SqlParameters, add them to the objCommand, etc....

objDataObject.BeginTransaction(IsolationLevel.ReadCommitted);
objDataObject.ExecuteNonQuery(objCommand);
objDataObject.CommitTransaction();
objDataObject.CloseConnection();
}

So indeed, a very thin wrapper around SqlClient, SqlConnection etc. I want to run several stored procs in a transaction, and the wrapper class doesn't allow me access to the SqlTransaction so I can't pass it from one component to the next. This led me to use a TransactionScope:

using (TransactionScope tx1 = new TransactionScope(TransactionScope.RequiresNew))
{
  method1();
  method2();
  method3();
  tx1.Complete();
}

When I do this, the DTC gets involved, and unfortunately our webservers don't have "allow remote clients" enabled in the MSDTC settings-- getting IT to allow that will be a fight.

I'd love to avoid DTC becoming involved but can I do it? Can I leave out the transactional calls in methods1-3() and just let the TransactionScope figure it all out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

要走就滚别墨迹 2024-08-22 00:21:00

SomeConnectionMethod() 的作用是什么?如果它在 method1()method2()method3() 中没有返回相同的连接,那么您就有一个分布式事务。因此DTC将参与协调本次交易。

因此,您必须在 SomeConnectionMethod() 中返回相同的连接,以防止 DTC 参与您的事务。

What does SomeConnectionMethod() do? If it doesn't return the same connection in method1(), method2() and method3(), then you have a distributed transaction. So DTC will be involved to coordinate this transaction.

So you have to return the same connection in SomeConnectionMethod() to prevent DTC to involve in your transaction.

や莫失莫忘 2024-08-22 00:21:00

为什么它不起作用:

我认为即使您共享相同的连接(如 larryq 所建议的),如果没有 DTC 的参与,它也不会起作用。

您想要一个事务范围来包装这些方法:

  • method1
    • 开始转换
    • 提交事务
  • 方法2
    • 开始转换
    • 提交事务
  • 方法3
    • 开始转换
    • 提交事务

在每个方法中,您开始并提交。如果方法 3 中出现问题,您需要回滚所有内容,包括方法 1 和 2 中已提交的事务。
为此,您需要一个涵盖所有 3 种方法的 DTC 事务

如果我错了,请纠正我,但我认为只有当您不在方法内开始和提交事务时,您才可以使用 TransactionScope 并避免使用 DTC。

它是如何工作的:

你真的需要使用带有开始和提交的事务吗?
难道你不能做这样的事情:

using (var scope = new TransactionScope(TransactionScopeOption.Required)) {
   objDataObject.ExecuteNonQuery(objCommand);
}

范围 Required 而不是 RequiredNew 使用现有事务(如果已经存在)。

如果我有什么错误,请随时纠正我。

Why it doesn't work:

I think even if you would share the same connection (as suggested by larryq), it wouldn't work without getting DTC involved.

You want a Transaction scope to wrap those methods:

  • method1
    • Begin Tran
    • Commit Tran
  • method2
    • Begin Tran
    • Commit Tran
  • method3
    • Begin Tran
    • Commit Tran

In each method you begin and commit. If something goes wrong in method3 you want to rollback everything, including the already committed transactions from method1&2.
To do that you need a DTC transaction that is spanning all 3 methods.

Correct me if I am wrong, but I think you can use TransactionScope and avoid the use of DTC only if you do not begin and commit transactions inside the methods.

How could it work:

Do you really need to use transactions with begin and commit?
Can't you do something like:

using (var scope = new TransactionScope(TransactionScopeOption.Required)) {
   objDataObject.ExecuteNonQuery(objCommand);
}

The Scope Required instead of RequiredNew uses an existing transaction if one already exists.

Please feel free to correct me if I got something wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文