9

私は使っている:

public class TransactionUtils
{
    public static TransactionScope CreateTransactionScope()
    {
        var TransactionOptions = new TransactionOptions();
        TransactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
        TransactionOptions.Timeout = TimeSpan.MaxValue;
        return new TransactionScope(TransactionScopeOption.Required, TransactionOptions);
    }
}

すべてのトランザクションを作成します。私が直面している問題は、 2 をネストTransactionUtils.CreateTransactionScope()するとエラーが発生することです: Time-out interval must be less than 2^32-2. Parameter name: dueTm. これは、子トランザクションを親トランザクションにアタッチしようとしていて、組み合わせたタイムアウトが大きすぎるためだと思います。

タイムアウトの設定を避けるために、新しく作成されたトランザクションがネストされたトランザクションになるかどうかを確認する方法はありますか?

別の方法は、パラメーターを渡すことです。これにより、パラメーターCreateTransactionScope()がネストされていてタイムアウトを設定していないことを伝えることができますが、それを自動的に処理する方法を見つけたいと思います。

4

2 に答える 2

34

非常に簡単な答えがあります:

System.Transactions.Transaction.Current != null

これは Framework 2.0 以降で機能します。

非公開フィールドにリンクするILを作成するために、なぜ他の答えがそのような深さになるのかわかりません。

于 2013-03-22T20:45:30.767 に答える
1

はい、可能です。次のコードがあります。自分で作ったわけではないのですが、どこで手に入れたか忘れてしまいました。元の作者に敬意を表しますが、グーグルで見つけたのを覚えています. 私は.net 4.0に使用していますが、これが他のバージョンとどの程度互換性があるかわかりません(特定のアセンブリの特定のクラスに依存します)。

以下のコードを使用すると、コード内のある時点で、トランザクション スコープの「内部」で実行しているかどうかを確認できます。

class TransactionScopeDetector {
    private Func<TransactionScope> _getCurrentScopeDelegate;

    public bool IsInsideTransactionScope {
        get {
            if (_getCurrentScopeDelegate == null) {
                _getCurrentScopeDelegate = CreateGetCurrentScopeDelegate();
            }

            TransactionScope ts = _getCurrentScopeDelegate();
            return ts != null;
        }
    }

    private Func<TransactionScope> CreateGetCurrentScopeDelegate() {
        DynamicMethod getCurrentScopeDM = new DynamicMethod(
          "GetCurrentScope",
          typeof(TransactionScope),
          null,
          this.GetType(),
          true);

        Type t = typeof(Transaction).Assembly.GetType("System.Transactions.ContextData");
        MethodInfo getCurrentContextDataMI = t.GetProperty(
          "CurrentData",
          BindingFlags.NonPublic | BindingFlags.Static)
          .GetGetMethod(true);

        FieldInfo currentScopeFI = t.GetField("CurrentScope", BindingFlags.NonPublic | BindingFlags.Instance);

        ILGenerator gen = getCurrentScopeDM.GetILGenerator();
        gen.Emit(OpCodes.Call, getCurrentContextDataMI);
        gen.Emit(OpCodes.Ldfld, currentScopeFI);
        gen.Emit(OpCodes.Ret);

        return (Func<TransactionScope>)getCurrentScopeDM.CreateDelegate(typeof(Func<TransactionScope>));
    }
}
于 2012-12-12T10:15:39.000 に答える