2

I have an Entity Framework dbContext and method which makes some manipulations with database. How to properly call it from multiple threads to avoid deadlocks, connection errors and so on? I tried it different ways, and I had a lot of exceptions.

public void Foo(Bar bar)
{
    using (var db = new ApplicationDbContext())
    {
        db.Documents.Add(bar);
        ...
        db.SaveChanges();
    }
}

static void Main(string[] args)
{
    ...
    var t1 = new Thread(()=>Foo(bar1));
    thread.Start();

    var t2 = new Thread(()=>Foo(bar2));
    thread.Start();
    ...
}

I never used threads before. Thanks for your help.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

2 Answers2

4

DbContext isn't thread safe and the best approach is to create separate instance of DbContext per unit of work (in your case per thread). See the recommendations.

Dmytro Mukalov
  • 1,949
  • 1
  • 9
  • 14
0

Create a single database context and share it with different threads and lock it while insert/update/delete records in database.

You can use design patterns like Factory to create single instance of DBContext.

If you try this solution and get failed let review your code, maybe you miss something in implementation of solution.

Mojtaba Tajik
  • 1,725
  • 16
  • 34
  • i actually did it, but i have issues with connections. And i read, that it's better to create dbContext each time. – Garruk The Wildspeaker Aug 26 '18 at 16:02
  • You get exceptions because of identity columns and something like theme which should handle by database server, when you start adding/editing or deleting records from database in different threads the process of handling concurrent request make uncommon problems. By creating database context in each thread you open different database connections which work independent and don't know anything about the state of database context in other threads. Imagine one thread remove record 437 and other thread try to update it ! it's normal behavior to get many exceptions and uncommon problems. – Mojtaba Tajik Aug 26 '18 at 16:05
  • Unhandled exception: System.InvalidOperationException: There is an open DataReader assigned to this Command, which you must first close. I don't know how to handle this. – Garruk The Wildspeaker Aug 26 '18 at 16:07
  • Btw it's not necessary to do this parralel. I just need to somehow do so that all the threads work out correctly. – Garruk The Wildspeaker Aug 26 '18 at 16:12
  • The DbContext is not thread safe, you should handle this problem using synchronization mechanism that i say before. you need to share your dbcontext or another object and use it for lock and the concurrent database operations. See this documentation about synchronization mechanisms : https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/threading/thread-synchronization – Mojtaba Tajik Aug 26 '18 at 16:23
  • I made it Singleton and lock it. Doesn't work. – Garruk The Wildspeaker Aug 26 '18 at 16:31
  • 1
    Please check the below topic first, maybe your problem is not about multi threading : https://stackoverflow.com/questions/6062192/there-is-already-an-open-datareader-associated-with-this-command-which-must-be-c – Mojtaba Tajik Aug 26 '18 at 16:35
  • 1
    Man, it's really helped. Love you! – Garruk The Wildspeaker Aug 26 '18 at 16:43