How to use injected DbContext in parallel methods in asp.net core and ef7?

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

Question

I have an Asp.net 5/Core 1 application with EF7. I register the DbContext in the DI container normally.

services.AddEntityFramework().AddSqlServer()
  .AddDbContext<MyDbContext>(options => options.UseSqlServer(connection));

Here is a small sample showing what I'm trying to do.

public class MyController : Controller
{
    MyDbContext _myDbContext;

    public MyController(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    public IActionResult Index()
    {
        //Just start these and don't wait for them to finish
        //We don't care if they succeed or not
        Task.Run(() => DoSomeLogging1());
        Task.Run(() => DoSomeLogging2());

        return View();
    }

    private void DoSomeLogging1()
    {
        _myDbContext.Items.ToList();
    }

    private void DoSomeLogging2()
    {
        _myDbContext.Items.ToList();
    }
}

Both DoSomeLoggingX methods will use the MyDbContext instance that was injected to the controller. Since the methods are run at the same time doing db queries at the same time, the other one will invariably fail with

The connection was not closed. The connection's current state is connecting.

MyDbContext also uses DI to get some references so I can't use it directly even if I wanted.

How can I run code in parallel and still be able to use my database through entity framework?

1
3
4/14/2016 8:29:45 AM

Accepted Answer

I also faced with this problem and for now I use my temporary solution EF 7 (Core). Create DBContext like AddTransient

If someone can provide more elegant solution I will be appreciated. Sometimes I really need to return instant result to user and in such cases await/async does not suit

1
5/23/2017 12:06:49 PM

Popular Answer

Simple answer: you can't. EF is not made for parallel sql execution (and never will be, I guess).

Less-simple answer. Probably this is not the right way to approach your problem (@Tseng made a point in his comments), but if you need to do a logging stuff like that you can:

  • make the two logging action sequential and share the same EF instance
  • use plain old SQL with a SqlConnection object (which works perfectly with parallel processing) - and it's faster
  • use a logging framework like NLog which supports log-and-forget approach


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