4

ここに質問があります。コードの一部のみを共有するContextを作成する方法はありますか。どう説明したらいいのかわからないので、例を出します。

私が持っているとしましょう:

using(Context ctx = new Context())
{
    ctx.Set("abc","abc");
    method1();
    method2();
}

および (方法 2 と同じ) :

public void method1()
{
    Context ctx = Context.Instance();
    string abc = ctx.Get("abc");
}

目標はContext.Instance()、メソッド内の が using で作成されたオブジェクトを返すことですが、スレッド セーフのままにしておく必要があります。つまり、呼び出しが using の外から、または別の using の中で同時に行われた場合、using に従ってコンテキストが返されるということです。Context.Instante()存在しない場合は新しいものを返しContextます(またはnull、後で適応します。それは重要ではありません)。

これは古典的な方法ではないことはわかっていますが、呼び出しごとにコンテキストを渡す必要はありません。real メソッドには多数の subs メソッドがあり、lasts だけがそれを必要としますが、最初から共通である必要があります。

目標は、すべての (そして唯一の) サブメソッドに共有される 1 つのトランザクションを作成することですが、最上位のメソッドは EF クラスにアクセスできません。私が持っている唯一の解決策は、セッションを使用してEFコンテキストを保存するか、セッションがないためバッチの静的に使用することです。それが私の目標ですが、問題はもっと一般的です。

質問をすることを躊躇しないでください。どのタグが追加されるのかよくわからないので、タグを追加します。

ありがとう !

編集

私は十分に明確ではなかったかもしれません。シングルトンでは不十分です。静的はすべてのインスタンス間で共有されます。using への 2 つの呼び出しが 2 人の異なるユーザーによって同時に行われた場合、Context はそれらに対して同じになりますが、私はそれらを異なるものにしたいと考えています。

理想的には、次のようなことを許可したいと思います:

using(Context ctx = new Context())
{
    ctx.Set("abc","abc");
    method1();
    using(Context ctx = new Context())
    {
        ctx.Set("abc","def");
        method2();
    }
    method1();
}

しかし、私はあまりにも多くを求めていると思います。

4

3 に答える 3

3

Context.Instance() メソッドでスレッド静的変数を管理します。最初の呼び出しでインスタンスを作成し、他の呼び出しでそれを使用できます。最初の呼び出しの使用が終了したら、それを破棄します。

スレッド静的アプローチを使用すると、各スレッドが独自のインスタンスを持つため、マルチスレッドの問題は発生しません。単一のスレッドでは、すべての「次のメソッドの実行」で同じインスタンスが使用されます。

アップデート:

いくつかのコード。それをデバッグすると、コンテキストが 1 つだけ作成され、2 番目の using ステートメントは最初の using ステートメントと同じコンテキストを受け取ります。

class Context : IDisposable {
    [ThreadStatic]
    private static Context _instance;
    [ThreadStatic]
    private static int _instanceCounter;

    public static Context Instance() {
        if (_instanceCounter == 0) {
            _instance = new Context();
        }
        _instanceCounter++;
        return _instance;
    }

    private static void Release() {
        _instanceCounter--;
        if (_instanceCounter == 0) {
            if (_instance != null)
                _instance.Dispose();
            _instance = null;
        }
    }

    public void Dispose() {
        Release();
    }
}

public class Test {
    public void Test1() {
        using (var context = Context.Instance()) {
            // do something
            Test2();
        }
    }

    private void Test2() {
        using (var context = Context.Instance()) {
            // identical context as in Test1
            // do something
        }
    }
}
于 2012-08-21T13:25:33.400 に答える
0

Maartenが言ったように、ThreadStaticを使用する必要があります。次のようなものが機能する可能性があります。

public class Context : IDisposable
{
    [ThreadStatic]
    private static Context context;

    private Context(Guid id)
    {
        this.Id = id;
    }

    public Guid Id
    {
        get;
        private set;
    }

    public static Context Instance()
    {
        if (context == null)
        {
            context = new Context(Guid.NewGuid());
        }

        return context;
    }

    public void Dispose()
    {
        context = null;
    }
}

次のコードを含むコンソールアプリを作成する場合は、それがどのように機能するかを理解する必要があります。

private static void Main(string[] args)
{
    Action action = () =>
    {
        using (var context = Context.Instance())
        {
            Console.WriteLine("Thread {0} - Context Id {1}", Thread.CurrentThread.ManagedThreadId, context.Id);

            using (var context2 = Context.Instance())
            {
                Console.WriteLine("Thread {0} - Context Id {1}", Thread.CurrentThread.ManagedThreadId, context.Id);
            }
        }

        Thread.Sleep(1000);
    };

    Task.Factory.StartNew(action);
    Task.Factory.StartNew(action);

    Console.ReadLine();
}

コンテキストが実際に最も外側のusingステートメントによってのみ破棄されるようにする場合は、スレッドごとにインスタンスが呼び出される回数もカウントする必要があります。

于 2012-08-21T13:44:28.080 に答える
0

Singleton 設計パターンが必要な場合は、ここにテンプレートがあります。クラスのインスタンスが1つだけ作成され、プログラムのすべての部分が同じインスタンスを使用することが保証されます

public class Singleton {

 private static Singleton instance; 

 private Singleton(){ // note private constructor

  // intialize code here
 }


 public static Singleton GetInstance(){

  if(instance == null){

   instance = new Singleton();
 }
   return instance;
 }

}

}

また、マルチスレッド環境では、Instance が null のときに 2 つのスレッドが GetInstance メソッドに入ることができ、両方が Singleton クラスの個別のインスタンスを初期化するケースを想像する必要があります。

呼び出すインスタンスを取得するにはSingleton.GetInstance()

于 2012-08-21T13:24:55.267 に答える