How can I take advantage of the DbContext Pooling out of ASP.NET Core LifeCycle?

asp.net-core c# entity-framework-core

Question

I have an object were per group of users to manage concurrent changes in memory. At a fix rate, say every six seconds, I take the current state of the changes and apply it to the database. The important part is there is a separate thread that requires a dbcontext instance that is outside of the ASP.NET Core MVC LifeCycle. This makes it difficult, or I do not know how I can take advantage of indecency injection.

Is there a way to take advantage of the AddDbContextPool in this problem space. There doesn't seem to be a way to Rent a AppDbContext directly and Microsoft warns against creating AppDbContext directly as its API is likely to change. As far as I know, I don't have a way to inject/Rent my database context into the thread that is doing the work.

I'm handing the thread using Reactive API where I create a Subjects and use the Sample pipe line as the sample below shows:

UpdateSubject
    .Sample(TimeSpan.FromSeconds(6))
    .Subscribe(x => {

        // This is where I'd like to take 
        // advantage of the dbcontext pooling
        using(AppDbContext db = new AppDbContext){

            // ...
            // Iterate Over Changes
            // ...

            db.SaveChanges();
        }

   });

My current Perceived options are.

  1. Do nothing: the architecture is already consolidating calls.
  2. Implement my own pool and research how to reset the context for each use myself,
  3. Use/implement Microsoft's internal class DbContextPool myself despite there warnings its strictly intended for internal use and the API may change
  4. Discover a way to make it apart of the ASP.NET Core MVC life cycle without changing how its functioning, I.E., find a way to take advantage of dependency injection in my use case.
  5. *open to suggestions
1
1
3/30/2019 7:35:07 PM

Accepted Answer

Asking the question helped me answer my own question, or find a solution. Everything below was tested with threads running outside of a request.

Turns out we can Inject the service provider to make our own instances through the API!

ReadOnly IServiceProvider _ServiceProvider;

MySingulation(IServiceProvider serviceProvider)
{
    _ServiceProvider = serviceProvider;
}

Once we have a handle to IServiceProvider through injection, we can use MVC Core API to create instances of our context

using(var serviceScope = _ServiceProvider.CreateScope())
{
    // Don't get confused -- Call GetService from the serviceScope and 
    // not directly from the member variable _ServiceProvider. 
    var context = serviceScope.ServiceProvider.GetService<YourAppDbContext>();

    // ...
    // Make use of the dbcontext
    // ...

}

Now, it just important to remember we make use of MVC Core Pooling in the Startup.cs to begin with.

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddDbContextPool<YourAppDbContext>(options => {
        options.UseSqlServer(settings.Connection);
    });

    // Oh, it's important the singultion was created within Core's LifeCycle/API
    services.AddSingleton<MySingulation>();
    //...
}   
1
3/30/2019 8:50:37 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