1

特定のデータベース接続でデータベース トランザクションを実行する機能を提供することを目的としたクラスを C# で作成しました。ただし、コードを実行しようとすると、Oracle と SQL Server でそれぞれ次の 2 つのエラーが発生します。私のコードを見ると、これを回避する簡単な方法はありますか?

オラクル

接続はすでにローカルまたは分散トランザクションの一部です

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.");
    }
4

2 に答える 2

3

問題は、接続オブジェクトで BeginTransaction を 2 回呼び出していたことにあることがわかりました。この問題はdatabaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); 、オーバーライド メソッドから削除することで解決されました。

于 2012-08-16T08:47:29.707 に答える
0

オーバーライド時にこの行を省略してください

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

そしてこれを変更します

databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = dbTransaction;

databaseConnectivityObject.DBFactoryDatabaseCommand.Connection= databaseConnectivityObject.DBFactoryDatabaseConnection;
于 2012-08-16T08:51:39.400 に答える