6

I cannot seem to find an answer to this question.

So in the frontend when the user loads a page we call an API for each item on that page (10 items). So that equals 10 API calls.

Most of the calls work but there are always a few that fail when trying to query the database resulting in the following error:

InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

Now I understand that Entity Framework is not thread safe but I am unsure how to get around this error.

Everywhere where I am using a DBContext it is always injected in using the built in .net core Ioc container.

Here is the DI setup

services.AddScoped<IOmbiContext, OmbiContext>();
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();

All of my repositories are setup in a Transient scope with the Context as Scoped according to this article: https://learn.microsoft.com/en-us/aspnet/core/data/entity-framework-6

Now I have tried changing the context to Transient and it still happens.

How can I avoid this?

More Information

The API Method:

[HttpGet("movie/info/{theMovieDbId}")]
public async Task<SearchMovieViewModel> GetExtraMovieInfo(int theMovieDbId)
{
    return await MovieEngine.LookupImdbInformation(theMovieDbId);
}

Which eventually calls the following where the exception is being thrown:

public async Task<RuleResult> Execute(SearchViewModel obj)
{
    var item = await PlexContentRepository.Get(obj.CustomId); <-- Here
    if (item != null)
    {
        obj.Available = true;
        obj.PlexUrl = item.Url;
        obj.Quality = item.Quality;
    }
    return Success();
}

PlexContentRepository

public PlexContentRepository(IOmbiContext db)
{
    Db = db;
}

private IOmbiContext Db { get; }
public async Task<PlexContent> Get(string providerId)
{
   return await Db.PlexContent.FirstOrDefaultAsync(x => x.ProviderId == providerId); <-- Here
}
Jamie Rees
  • 7,973
  • 2
  • 45
  • 83
  • Does this apply https://stackoverflow.com/questions/20628792/multi-async-in-entity-framework-6#20635076 – Nkosi Aug 25 '17 at 12:55
  • @Nkosi No, everything is fully asynchronous all the way down the stack using the `async` and `await` keywords. – Jamie Rees Aug 25 '17 at 12:56
  • 1
    Are you able to show the API being called that throws the error – Nkosi Aug 25 '17 at 12:58
  • @Nkosi There is quite a lot of code, but i've updated my question to include the important bits. The software is Open Source so I can include a link to the Github project if anyone will find that useful – Jamie Rees Aug 25 '17 at 13:04
  • Already looking at the repo. :) – Nkosi Aug 25 '17 at 13:04
  • So far from my initial review of the code it may be related to sqlite. That is my initial assessment. Will follow up if confirmed. – Nkosi Aug 25 '17 at 13:21
  • @Nkosi Thank you very much for investigating! – Jamie Rees Aug 25 '17 at 14:36
  • How are the `IRules` added to the object graph. Can't seem to find how they get into the container – Nkosi Aug 25 '17 at 15:09
  • I believe the issue is related to the lifetime scope of the objects in use. – Nkosi Aug 25 '17 at 15:12
  • @Nkosi But i've tried Transient and Scoped... – Jamie Rees Aug 28 '17 at 20:33
  • @JamieRees I have same problem ,for god's sake, do you have any success after 2 month with this problem ? It drives me crazy... – paradise_human Nov 13 '17 at 16:01
  • @paradise_human Yes I did fix it, but I cannot remember how... I did upgrade to .Net Core 2.0. You can take a look at the commits around this time if you want: https://github.com/tidusjar/Ombi/commits/DotNetCore – Jamie Rees Nov 13 '17 at 16:10
  • @JamieRees I used .net core 2 , too . as I investigate your code my pattern is like you. I dont know where is the problem. – paradise_human Nov 13 '17 at 16:25
  • @JamieRees The Github repro is down? I have the same issue with Core 2.0, shame that you don't remember how it was solved :(. – Lars Thorén Apr 19 '18 at 13:27
  • @LarsThorén That branch has been deleted so just look at https://github.com/tidusjar/Ombi/ – Jamie Rees Apr 19 '18 at 14:02

1 Answers1

-2

If you use Entity Framework Core usually you do not need to add your Database Context as an additional service

I recommend to setup your DbContext in the Startup.cs as following:

services.AddEntityFrameworkSqlServer()
            .AddDbContext<OmbiContext>();

Followed by a Controller class for your API calls taking the DBContext as constructor parameter.

public class ApiController : Controller
{
    protected OmbiContext ctx;
    public ApiController(OmbiContext dbctx)
    {
        ctx = dbctx;
    }

    public async Task<IActionResult> yourAsyncAction()
    {
        // access ctx here
    }
}
Ole K
  • 754
  • 1
  • 9
  • 32
  • I don't think this really answers the question. The Context has also been injected in to assist with Unit Testing, following the Inversion of control responsibility – Jamie Rees Aug 25 '17 at 13:05
  • IMO - The questioner is building a second service which may cause the error mentioned – Ole K Aug 25 '17 at 13:08