Create EF Core DBContext in controller for multi-threading?

c# entity-framework-core

Question

In one of my controllers, I have an async method that has to make a few db calls simultaneously, so I set it up like this:

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

I store the contexts that are injected. In the particular method:

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

Inside of the WhenAll, I need to use the xxxContext for each item, so I get the non-thread safe exception.

What is the correct way to create a new DbContext? Right now I'm doing:

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

So I'm getting the connection string from the existing context that was injected and use that to create a new one.

The connection strings are stored in appSettings.json. In the "ConnectionStrings" section.

Is there a cleaner way to create the contexts for multi-threading?

1
1
5/4/2017 10:46:53 PM

Popular Answer

For this purpose I created something like factory class which can provide context per call. For your case it can be

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>();
    }
}

Than you should call Init method in Startup

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

You can look my approach for this on github

0
5/4/2017 7:30:55 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow