【问题标题】:C# Transactions on Oracle & SQL Server via ADO.NET failing通过 ADO.NET 在 Oracle 和 SQL Server 上的 C# 事务失败
【发布时间】:2012-08-16 08:43:03
【问题描述】:

我用 C# 编写了一个类,旨在提供在给定数据库连接上运行数据库事务的能力。但是,当我尝试运行代码时,我分别在 Oracle 和 SQL Server 上收到以下两个错误。查看我的代码是否有简单的解决方法?

甲骨文

连接已经是本地或分布式事务的一部分

SQL Server 2008

SqlConnection 不支持并行事务

基类

  public abstract class DbFactoryDatabaseTransaction
  {
    public void DoTransaction(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject)
    {
        databaseConnectivityObject.PrepareConnection();

        DbTransaction dbTransaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction();

        try
        {
            ExecuteSql(databaseConnectivityObject, dbTransaction);

            dbTransaction.Commit();
        }
        catch (Exception ex)
        {
            dbTransaction.Rollback();

            databaseConnectivityObject.Close();

            throw;
        }
        finally
        {
            dbTransaction.Dispose();
        }
    }


    /// <summary>
    /// A method to allow the caller to decide how the SQL statements are called as part of a transaction
    /// </summary>
    public abstract void ExecuteSql(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject, DbTransaction dbTransaction);
}

覆盖方法

public override void ExecuteSql(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject, DbTransaction dbTransaction)
    {
        //oracle
        List<string> transactions = new List<string>
            {
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (1, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))",
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (2, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))",
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (3, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))",
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (4, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))",
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (5, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))",
                "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (6, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))"
            };

        databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction();

        foreach (var transaction in transactions)
        {
            databaseConnectivityObject.DBFactoryDatabaseCommand.CommandText = transaction;
            databaseConnectivityObject.DBFactoryDatabaseCommand.CommandType = CommandType.Text;
            databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = dbTransaction;
            databaseConnectivityObject.DBFactoryDatabaseCommand.ExecuteNonQuery();
        }
    }

调用方法

    public void RunTransaction()
        {
        IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject = new DbProviderFactoryConnectionBasic();

        DoTransaction(databaseConnectivityObject);
        }

测试方法

    [TestMethod()]
    public void RunTransactionTest()
    {
        TmaNoticeToClusteredEntityValidation target = new TmaNoticeToClusteredEntityValidation(BindVariables, SqlFactory, Dialect); 
        target.RunTransaction();
        Assert.Inconclusive("A method that does not return a value cannot be verified.");
    }

【问题讨论】:

    标签: c# oracle sql-server-2008 ado.net transactions


    【解决方案1】:

    事实证明,问题实际上是我在连接对象上调用 BeginTransaction 两次()。通过从覆盖方法中删除 databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); 解决了这个问题。

    【讨论】:

      【解决方案2】:

      在覆盖时省略这一行

      databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction();
      

      然后改变这个

      databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = dbTransaction;
      

      databaseConnectivityObject.DBFactoryDatabaseCommand.Connection= databaseConnectivityObject.DBFactoryDatabaseConnection;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-09
        • 1970-01-01
        相关资源
        最近更新 更多