"A second operation started on this context" EF core 3.1 concurrency breaking change

.net-core async-await c# entity-framework-core

Question

I'm migrating from netcoreapp 2.1 to 3.1, and I've found a breaking change for EF core 3.1 that I can't resolve.

Previously in 2.1, this worked:

taskList.Add(MethodOne(myRequestObject));
taskList.Add(MethodTwo(myRequestObject));

await Task.WhenAll(taskList);

where both methods only read(never changed) from the db context and look something like this:

private async Task MethodOne(RequestObject myRequestObject)
{
    var entity = await DbContext
    .MyDbSet
    .OrderByDescending(x => x.SomeProperty)
    .FirstOrDefaultAsync(x => x.Id == myRequestObject.Id);

    if (entity != null)
        myRequestObject.SomeRequestProperty = entity.AnotherProperty;
    }
}

In 3.1, even when I'm just reading and not changing the entities, the DB context ConcurrencyDetector thinks it has EnterCriticalSection which causes an exception when the second method tries to await on the DbContext:

InvalidOperationException: A second operation started on this context before a previous operation completed

So, to work around this I replaced await Task.WhenAll(taskList) with the following:

foreach (var task in taskList)
{
    await task;
}

However, this does not work. The same error occurs, as if the second method begins execution without waiting for the first.

For baseline sanity, I also tried the following which does work(but is not an ideal solution for the real code of my app):

await MethodOne(myRequestObject);
await MethodTwo(myRequestObject);

So here are my questions:

  1. Is there a way to continue to tell EF core 3.1 to allow concurrency when I know it is safe.

  2. If not, why the heck is my foreach workaround not working?

1
0
3/6/2020 6:11:58 PM

Popular Answer

Entity Framework DbContext is not thread safe. You can execute only one query at a time otherwise you will get an exception like you did above.

I suppose that you use our repository multiple times during same request in parallel that's why you get the exception. If you don't create a transaction per request you can simply make repository transient. In this case new repository will be created fro each instance of your service and you will avoid concurrency issue.

4
4/15/2017 10:51:29 AM


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