【问题标题】:Tracking down a distributed tranaction error追踪分布式事务错误
【发布时间】:2013-05-16 16:27:57
【问题描述】:

如何追踪分布式传输错误?有什么方法可以确定所有连接仍然打开吗?我需要找到没有正确关闭的交易吗?

当我从适配器填充表时,使用以下代码偶尔会出现分布式事务错误。我怀疑错误可能不在此代码中,但这是错误倾向于弹出的地方,仅在第二次尝试时,第一次总是可以正常工作。

using (OracleConnection oraConnection = new OracleConnection(connectionString)){
 using (OracleCommand oraCommand = new OracleCommand( "DB_SCHEMA." + rmd.storedprocName, oraConnection )){
    oraCommand.CommandType = CommandType.StoredProcedure;

    if ( rmd.parameters != null ){
        for ( int i = 0; i <= rmd.parameters.GetUpperBound( 0 ); i++ )
        {
            OracleParameter oraParameter = new OracleParameter();
            oraParameter.ParameterName = rmd.parameterNames[ i ];
            oraParameter.OracleDbType = rmd.parameterTypes[ i ];
            oraParameter.Size = 15;

            string dataType = oraParameter.OracleDbType.ToString().ToUpper();

            switch ( dataType )
            {
                case "VARCHAR2":
                    oraParameter.Value = rmd.parameters[ i ].ToString();
                    break;
                case "CHAR":
                    oraParameter.Value = rmd.parameters[ i ].ToString();
                    break;
                case "NUMBER":
                    oraParameter.Value = Convert.ToDouble( rmd.parameters[ i ] );
                    break;
                case "DATE":
                    oraParameter.Value = Convert.ToDateTime( rmd.parameters[ i ] );
                    break;
                default:
                    oraParameter.Value = rmd.parameters[ i ].ToString();
                    break;
            }

            oraCommand.Parameters.Add( oraParameter );

        }
    }

  oraCommand.Parameters.Add( "RS", Oracle.DataAccess.Client.OracleDbType.RefCursor).Direction = ParameterDirection.Output;
   OracleDataAdapter oraDataAdapter = new OracleDataAdapter( oraCommand );
   oraDataAdapter.Fill( dataTable );  //< -- error is thrown here
 }
}

【问题讨论】:

    标签: c# oracle database-connection distributed-transactions


    【解决方案1】:

    我不确定问题出在哪里,但我怀疑这是由于使用了OracleDataAdapter 而您已经拥有OracleCommandOracleConnection 对象。

    我认为使用OracleDataReader 填充您的表格并从您的连接中调用Open()Close() 方法会更简洁。

    将所有参数分配给oraCommand 后,试试这个而不是DataAdapter

        oraConnection.Open();
        OracleDataReader dr = oraCommand.ExecuteReader();
        dataTable.Load(dr);
        oraConnection.Close();
    

    同样,我认为这不一定会“修复”您的事务错误,但它应该确保您在执行存储过程时只有一个打开的连接,从而使连接更易于管理。

    以下是使用TransactionScope 对象进行数据访问的示例:

        try
        {
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = IsolationLevel.ReadCommitted}))
            try
            {
                CallYourDataAccessMethodsHere();
                scope.Complete();
            }
            catch (Exception ex)
            {
                //Handle or log the error during the transaction
            }
        }
        catch (Exception ex)
        {
            //This will catch a TransactionAbortedException and hopefully help track down the problem
        }
    

    【讨论】:

    • 在 msdn 中,它说“在任何给定时间都可以打开多个 OracleDataReader。” (msdn.microsoft.com/en-us/library/ab4kxd8h.aspx) 所以我尝试使用它打开多个连接,但我仍然收到错误。
    • 再想一想,您可能需要考虑对所有数据访问方法使用TransactionScope,以确保在对数据库的所有事务范围内完成所有访问和读取。另一种可能性是存储过程本身出现问题,也许尝试在那里进行一些错误处理而不是回滚?或者把存储过程贴出来,我们可以看看。
    • 我在原始答案中添加了一些代码来演示 TransactionScope 对象的使用。
    猜你喜欢
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 2011-11-05
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多