为啥我在使用 TransactionScope 时会出错?

Posted

技术标签:

【中文标题】为啥我在使用 TransactionScope 时会出错?【英文标题】:Why Am I Getting Error Using TransactionScope?为什么我在使用 TransactionScope 时会出错? 【发布时间】:2021-03-04 12:21:34 【问题描述】:

大家!

我在使用 TransactionScope 时遇到问题。我希望我的网络方法是事务性的。如果发生任何异常,我希望回滚所有数据库更改。否则,提交。请参阅下面的错误消息。

System.ApplicationException:someClass :: Method public 中的错误 returnType methodName(parameterType 参数) :

System.ApplicationException: someClass :: Method private中的错误 字符串 someMethod() :

System.Data.Odbc.OdbcException (0x80131937):

错误 [08003] [Sybase][ODBC 驱动程序]连接未打开

在 System.Data.Odbc.OdbcConnection.Open_EnlistTransaction(事务 交易)

在 System.Data.Odbc.OdbcConnectionOpen.EnlistTransaction(Transaction 交易)

在 System.Data.Odbc.OdbcConnection.EnlistTransaction(事务 交易)

在 System.Data.Odbc.OdbcConnection.Open()

在 c:\somePath\someClass.cs:line 35 中的 someNameSpace.someMethod() 处

以下是我的代码的摘录。我做错了什么?

 [WebMethod]
 public returnType methodName(parameterType parameter)
 
     using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
     
         try
         
             var someValue = someMethod();
                 :
                 :
                 :

             transactionScope.Complete();

             return response;
         
         catch (Exception ex)
         
             return ErrorMessages(ex);
         
     
 

 private string someMethod()
 
     var commandText = "...some valid SQL expression...";
     var commandType = CommandType.Text;

     try
     
         using (var odbcConnection = new OdbcConnection(DefaultDbConnection.ToString()))
         
             using (var odbcCommand = new OdbcCommand(commandText, odbcConnection))
             
                 odbcConnection.Open();  // Exception is thrown here!
                 odbcCommand.CommandType = commandType;

                 using (var reader = odbcCommand.ExecuteReader())
                 
                     reader.Read();
                     return reader.GetString(0);
                 
             
         
     
     catch (Exception ex)
     
         throw new ApplicationException("Error in someMethod.", ex);
     
 

提前感谢您的帮助!

【问题讨论】:

大概你是说相同的代码在没有事务范围的情况下也能正常工作,对吗?最终:并非所有提供商都支持该 API,我建议无论如何反对它。你在这里谈什么? (使用 ODBC 很难知道这一点,因为这是一个备用的遗留 API)。请注意,您可以尝试将 Open() 调用移到命令构造之上。 嗨,马克!...感谢您的及时回复。我很高兴我的问题引起了您的注意。我希望你能回应。我看过你的很多回复。我总是觉得它们很有帮助...... 当我注释掉 "using (var transactionScope = new TransactionScope())" 和 "transactionScope.Complete()" 行时,Web 方法可以完美运行,完全符合预期,没有错误或警告。只有当我引入 TransactionScope 时,当 odbcConnection 尝试登记事务时,“odbcConnection.Open()”才会引发以下异常: System.Data.Odbc.OdbcException (0x80131937): ERROR [08003] [Sybase][ODBC Driver]连接未打开 我尝试了以下... using (var transactionScope = new TransactionScope()) using (var transactionScope = new TransactionScope(TransactionScopeOption.Required)) // 默认使用 (var transactionScope = new TransactionScope( TransactionScopeOption.RequiresNew)) 它们都不起作用。 我在“使用 (var odbcCommand = new OdbcCommand(commandText, odbcConnection))”之前尝试过“odbcConnection.Open()”之前。那也没用。 【参考方案1】:

最终,并非所有连接类型(也不是所有平台)都支持基于事务范围的事务,即使它们支持:由于与多个系统通信时的范围问题,它们可能是不可预测的,需要 DTC 之类的东西。

相反,我强烈建议:不要使用事务范围(除非你有充分的理由)。相反,更喜欢更简单且支持更广泛的 ADO.NET 事务模型:

在连接上使用BeginTransaction(或异步等效项)以(不出所料)开始事务 在代码中携带该事务实例 在每个命令上设置事务属性(我一直不明白为什么有必要这样做,因为它是通过连接隐含的,但是:确实如此) 确保在最后提交或中止事务,最好使用try/catch/finally,这样它在成功和失败中都能正确发生

【讨论】:

根据您之前的回复,我决定放弃 TransactionScope 并以“老式”方式进行...使用BeginTransactiontry/catch/finally ......实际上你在上面写的。我真的很感谢您的帮助...谢谢!

以上是关于为啥我在使用 TransactionScope 时会出错?的主要内容,如果未能解决你的问题,请参考以下文章

错误 - 具有多个数据库连接的 LINQ/TransactionScope

TransactionScope 过早完成

在 .NET Core/.NET 5+ 中使用 TransactionScope 和 SQL 连接池时如何避免 PlatformNotSupportedException

嵌套 TransactionScope 在测试中失败

如何在多实例应用程序上处理 TransactionScope?

忽略特定查询的 TransactionScope