5
private void btnConfigure_Click(object sender, EventArgs e)
{
    try
    {
        dbConfigure dc = new dbConfigure();
        SqlTransaction tr = conn.BeginTransaction();
        cmd.Transaction = tr;
        if (dc.configuration(cmd, ps.tableNames))
            tr.Commit();
        else
        {
            tr.Rollback();
            mesg.show("Transaction is Rolled back");
        }
    }
    catch (Exception ex)
    {
        mesg.show(ex.Message);
    }
}

メソッドのどこかで問題が発生するconfigurationと、 false が返され、メッセージが表示されますTransaction is Rolled Back。しかし、実際にはトランザクションは完全にはロールバックされず、この関数によって行われたデータベース構造の変更の一部は、ロールバックにもかかわらずそこにとどまりますが、これはまったく望ましくありません。私の質問は、トランザクションのロールバックの誤動作の可能性は何ですか?

私のプロジェクトには、共有された(上記の)メソッド以外にトランザクションはありません

ささいな詳細

configurationクラスの非常に長い/複雑な関数を呼び出していdbConfigureます。データベース構造に必要な変更を加えます。例えばそれ

  1. foriegnKeys をドロップします
  2. 主キーを削除
  3. 自動インクリメント フィールドを削除します

    ドロップする前にこれらのキーを保存し、目的の順序/位置で再作成します

connSqlConnectionすでに開かれています。これ以外の接続は使用しません

cmdconn.CreateCommand()これ以外の場所ではコマンドを使用しません

このプロセス全体で接続を閉じることはありませんが、SqlDataReader はconfigurationジョブを実行するときに関数で閉じられます。

4

2 に答える 2

7

データベース構造への変更はトランザクションではないため、新しいテーブルの作成をロールバックすることはできません。たとえば、

BS。ほとんどの DDL はトランザクション対応であり、ロールバックできます。非トランザクション コンポーネント (データベースへの新しいファイルの追加など、ファイル システムなど) との対話を含む変更のみをロールバックすることはできません。非トランザクションの DDL も、アクティブなトランザクションで呼び出された場合、非常に明示的に例外を発生させます。

テーブルの追加と変更は非常に明示的なトランザクションであり、例で簡単に説明できます。

begin transaction;
create table foo (a int);
select * from sys.tables where object_id = object_id('foo');
rollback;
select * from sys.tables where object_id = object_id('foo');

したがって、問題はOPの欠落コード、投稿されていない部分にあります。

一般的なコメントとして、可能な場合は System.Transactions を使用する必要があります (デフォルトのコンストラクターが壊れていることを考慮して)。SqlConnection.BeginTransaction を使用する場合は、IDisposable に依存することをお勧めします。

using (SqlTransaction trn = conn.BeginTransaction())
{
   ...
   trn.Commit ();
}

ただし、System.Transactions はコード規則に依存しないため、優先する必要があります。トランザクション スコープ内のコード SqlClient は自動的に登録されます。

そしてところで、エラー時に設定関数を発生させ、falseを返さないでください。

そして、根底にある実際の問題: 1 つのトランザクションに登録することができない、長くて複雑な移行を処理する方法 (例: 単純に大量のログが生成される可能性がある)。その答えは、移行の開始時にデータベースのバックアップを作成し、移行が失敗した場合にこのバックアップから復元することが唯一の実行可能なオプションであるということです。移行を元に戻すために、すべての移行操作に対してテスト済みで信頼性の高い手動の補正アクションを提供する代替手段は、信じられないほど困難で、エラーが発生しやすく、最終的には不要です。

于 2012-11-15T12:14:37.430 に答える
1

これは、コードで SqlTransaction を作成するのではなく、TransactionScope を使用して行うことができます。このようなもの:

using (TransactionScope transaction = new TransactionScope())
{
    ...perform your database action here

    scope.Complete()
}
于 2012-11-15T11:56:59.517 に答える