2017-05-04 8 views
1

は、私はいくつかのデシベルを同時に呼び出しを行う必要があり、非同期メソッドを持っているので、私はこのようにそれを設定します。マルチスレッドのためにコントローラにEF Core DBContextを作成しますか?私のコントローラの一つで

public xxxController(IConfiguration configuration, xxxContext xxxContext, xxx2Context xxx2Context) 
    : base(xxxContext) 

私が注入されたコンテキストを格納します。特定の方法では:WhenAllの内部

var v = await Task.WhenAll(...) 

、私は、各項目のxxxContextを使用する必要があるので、私は非スレッドセーフで例外を取得します。

新しいDbContextを作成する正しい方法は何ですか?今私がやっている:

var v = new DbContextOptionsBuilder<xxxContext>(); 
v.UseSqlServer(_xxxContext.Database.GetDbConnection().ConnectionString);  
xxContext e = new xxContext(v.Options); 

をだから私は注入し、新しいものを作成するためにそれを使用して、既存のコンテキストからの接続文字列を取得しています。

接続文字列はappSettings.jsonに格納されます。 「ConnectionStrings」セクション。

マルチスレッドのコンテキストをよりクリーンに作成する方法はありますか?

答えて

0

この目的のために、コールごとにコンテキストを提供できるファクトリクラスのようなものを作成しました。あなたのケースのために、それはあなたがあなたがこの中にあなたの非同期メソッドを実行し、私は恐れてgithub

0

に、このための私のアプローチを見ることができます

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    AppDependencyResolver.Init(app.ApplicationServices); 
    //other configure code 
} 

スタートアップ

Initメソッドを呼び出す必要以上

public class AppDependencyResolver 
{ 
    private static AppDependencyResolver _resolver; 

    public static AppDependencyResolver Current 
    { 
     get 
     { 
      if (_resolver == null) 
       throw new Exception("AppDependencyResolver not initialized. You should initialize it in Startup class"); 
      return _resolver; 
     } 
    } 

    public static void Init(IServiceProvider services) 
    { 
     _resolver = new AppDependencyResolver(services); 
    } 

    private readonly IServiceProvider _serviceProvider; 

    private AppDependencyResolver(IServiceProvider serviceProvider) 
    { 
     _serviceProvider = serviceProvider; 
    } 

    public xxxContext CreatexxxContextinCurrentThread() 
    { 
     var scopeResolver = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope(); 
     return scopeResolver.ServiceProvider.GetRequiredService<xxxContext>(); 
    } 
} 

することができ方法

var task = Task.Run(() => MyAsynchronosMethod()); 

DbContext操作は入出力操作で、同時に実行するために別のスレッドで実行する必要はありません。あなたはそれを新しいスレッドなしで動かすことができます。

public MyController(IConfiguration configuration, AContext aContext, BContext bContext) 
    : base(aContext) 
{ 
    _aContext = aContext; 
    _bContext = bContext; 
} 

public Task<IActionResult> GetSomething(int id) 
{ 
    var customerTask = aContext.Customers 
            .FirstOrDefaultAsync(customer => customer.Id == id); 
    var sellerTask = aContext.Sellers 
            .FirstOrDefaultAsync(seller => seller.CustomerId == id); 
    var ordersTask = bContext.Orders 
            .Where(order => order.CustomerId == id) 
            .ToListAsync(); 
    var invoicesTask = bContext.Invoices 
            .Where(invoice => invoice.CustomerId == id) 
            .ToListAsync(); 
    var allTasks = new[] { customerTask, sellerTask, ordersTask, invoicesTask}; 
    await Task.WhenAll(allTasks); 

    // Do stuff with result of completed tasks 

    Return OK(calculatedResult); 
} 

上記の方法では、応答を待たずにすべてのクエリをほぼ同時に送信します。すべての照会が送信された後でのみ、応答の待機を開始します。
すべてのクエリ結果が到着したら、データを処理できます。すべての操作は1つのスレッドで実行されます。

関連する問題