Deadlock on Linq to Entity Framework Core 2.0 Table

async-await asynchronous entity-framework-core linq

Question

I'm getting what I think to be a deadlock when trying to run a bunch of linq queries in parallel.

I am running a Task.WhenAll() on this method:

public async Task<MetabuildScan> GetLatestMetabuildScanAsync(string buildId)
{
    var metabuildScanStatuses = new[] { "Completed", "Referenced" };

    // Get the latest metabuild scan for this image build
    var latestScan = await (from scan in _qsaContext.MetabuildScans
                           where scan.SoftwareImageBuildId == buildId
                           && metabuildScanStatuses.Contains(scan.SIScanStatus)
                           orderby scan.SIScanStartedOn descending
                           select scan).FirstOrDefaultAsync();

    // If there is a related scan, then use that one, else, use the one we just got
    var latestCompletedScanId = latestScan?.RelatedScanId ?? latestScan?.Id;

    return await _qsaContext.MetabuildScans
                 .FirstOrDefaultAsync(scan => scan.Id == latestCompletedScanId);
}

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

_qsaContext was created using Entity-Framework Core.

At first, I thought the FirstOrDefaultAsync would fix my issue (I had a non-asynchronous FirstOrDefault in there at first), but it didn't.

I'm wondering what the best solution to get around this deadlock would be. The table I am selecting from is a large table, so I can't pull the whole table into memory.

1
0
7/7/2018 12:40:24 AM

Popular Answer

Entity Framework DbContext is not thread safe. You can't run parallel queries against it like you are attempting to do.

If you need to have a shared context for your queries that you'll need to await each one individually and sequentially.

If they don't need a shared context but do need to run in parallel then you'll need to have a separate context for each query.

If using a DI framework, perhaps you can look into making your DbContext Transient (instead of what I'm assuming is Scoped) and injecting that into a query class that will call your query methods.

0
7/10/2018 3:38:54 PM


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