4

SQL呼び出しが失敗した場合、たとえばデッドロックのためにタイムアウトした場合、トランザクションはゾンビトランザクションに変わる可能性があります.私のコードまたはフレームワークコードのいずれかがロールバックを行うと思います. SqlTransaction は null ではありませんが、Rollback() を実行しようとすると、ゾンビがエラーをスローする可能性があります。.IsZombie プロパティが見つかりません。

// Make sure the transaction is not null
if (transaction != null)
{
    //TODO: Is there a way to test a transaction to see if it can be rolled back?
    transaction.Rollback();  
}
4

4 に答える 4

2

.NET 2.0 の System.Transactions 名前空間の TransactionScope クラスを使用してみることができます。このクラスを使用すると、トランザクションが自動的にキャンセルされてロールバックされるまでのタイムアウトを指定できます。.NET 2.0 以降の ADO.NET は TransactionScope に対応しており、データベースの呼び出し時に DbTransaction が存在する場合は、DbTransaction をスコープに自動的に登録します。

public void DoSomething()
{
    using (TransactionScope scope = new TransactionScope(TransactionScopeOptions.Required, TimeSpan.FromSeconds(60)))
    {
        MyDac();

        scope.Complete(); // If timeout occurrs, this line is never hit, scope is disposed, which causes rollback if Complete() was not called
    }
}

public class MyDac()
{

    using (SqlConnection ...)
    {
        using (SqlCommand ...)
        {
            // Do something with ADO.NET here...it will autoenroll if a transaction scope is present
        }
    }
}

TransactionScope は System.Transactions.Transaction を内部的に作成します。これにより、既定では、1 つのサーバーのみが関与している場合に SQL Server への軽量トランザクションが許可されます。トランザクションに複数のサーバーまたは分散リソース マネージャーが関与している場合、TransactionScope によってラップされたトランザクションは分散トランザクションに昇格され、MSDTC による調整が必要になり、TransactionScope の使用が複雑になる可能性があります。すべてのトランザクションが軽量である場合、TransactionScope は、db トランザクションを手動で管理するよりも多くの利点を提供できます。

于 2009-05-23T17:17:06.080 に答える
1

申し訳ありませんが、反対することは避けられません。クライアント トランザクションは、ビジネス プロセスのアトミック操作を可能にするものです。すべてのトランザクション操作を DB に移動する場合は、常にビジネス ロジックを DB に移動します。これはアプローチですが、プログラムでやや複雑なロジックを使用する場合は、強くお勧めしません。whiles/for/foreachs、文字列チェック、およびその他の簡単な操作を DB に移行するのは非常に困難です (場合によっては、不可能なこともあります)。ただし、デッドロック ヒントは非常に有用であり、クライアント アプリケーションをさらに制御できるようです (私の意見では、これが最善の方法です)。

乾杯

于 2009-12-21T11:08:05.660 に答える
1

私が知っている古い質問ですが、最近この問題に対処していて、SqlTransactions を安全にコミット/ロールバックするための小さなヘルパー関数を作成しました。他の誰かがこの問題の解決策を探している場合に備えて、投稿すると思いました。

public void CompleteTransaction(SqlTransaction transaction, bool isRollback) {
    if (transaction == null) { return; }
    try {
        if (isRollback) { 
            transaction.Rollback(); 
        } else { 
            transaction.Commit(); 
        }
    } catch (InvalidOperationException ex) {
        // In my case, I just ignored exceptions due to zombie transactions, 
        // but you could handle it differently depending on your needs
        if (ex.TargetSite == null || ex.TargetSite.ToString() != "Void ZombieCheck()") {
            throw; // Not a zombie transaction, so re-throw the exception
        }
    }
}

ゾンビ トランザクションによる例外スローの例外の詳細を調べていたときに、TargetSite がVoid ZombieCheck()であることに気付きました。したがって、私のソリューションでは、TargetSite がそのように設定されていない場合、ゾンビ トランザクションによるエラーではないと想定しています。

于 2018-05-01T17:00:53.783 に答える
0

@@ERROR = 1205 をテストして、クエリがデッドロックの犠牲になっているかどうかを判断できるデータベース内にトランザクション処理コードを配置することを検討してください。デッドロックの場合は、再試行または ROLLBACK できます。クライアント アプリケーションにトランザクションの作成と管理を許可することは少し危険であり、可能であれば避けることをお勧めします。

お役に立てれば、

明細書

于 2009-05-23T12:57:04.600 に答える