How to use injected DbContext in parallel methods

2019-05-14 22:13发布

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?

2条回答
老娘就宠你
2楼-- · 2019-05-14 22:53

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
查看更多
叼着烟拽天下
3楼-- · 2019-05-14 22:55

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

查看更多
登录 后发表回答