Подтвердить что ты не робот

EF 6 - Как правильно выполнять параллельные запросы

При создании отчета я должен выполнить 3 запроса, которые связаны с отдельными объектами одного и того же контекста. Поскольку они довольно тяжелые, я решил использовать .ToListAsync();, чтобы они запускались параллельно, но, к моему удивлению, я получаю исключение из этого...

Каков правильный способ параллельного выполнения запросов с использованием EF 6? Должен ли я вручную запускать новые задачи?

Изменить 1
Код в основном

using(var MyCtx = new MyCtx())
{
      var r1 = MyCtx.E1.Where(bla bla bla).ToListAsync();
      var r2 = MyCtx.E2.Where(ble ble ble).ToListAsync();
      var r3 = MyCtx.E3.Where(ble ble ble).ToListAsync();
      Task.WhenAll(r1,r2,r3);
      DoSomething(r1.Result, r2.Result, r3.Result);
}
4b9b3361

Ответ 1

Проблема заключается в следующем:

EF не поддерживает обработку нескольких запросов через один и тот же объект DbContext. Если ваш второй асинхронный запрос к тому же экземпляру DbContext запускается до того, как первый запрос завершится (и в этом вся суть), вы получите сообщение об ошибке, которое ваш запрос обрабатывает в отношении открытого DataReader.

Источник: https://visualstudiomagazine.com/articles/2014/04/01/async-processing.aspx

Вам нужно будет изменить код так:

async Task<List<E1Entity>> GetE1Data()
{
    using(var MyCtx = new MyCtx())
    {
         return await MyCtx.E1.Where(bla bla bla).ToListAsync();
    }
}

async Task<List<E2Entity>> GetE2Data()
{
    using(var MyCtx = new MyCtx())
    {
         return await MyCtx.E2.Where(bla bla bla).ToListAsync();
    }
}

async Task DoSomething()
{
    var t1 = GetE1Data();
    var t2 = GetE2Data();
    await Task.WhenAll(t1,t2);
    DoSomething(t1.Result, t2.Result);
}

Ответ 2

Проверьте https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets

Из документации:

Чередование операторов операторов SELECT и BULK INSERT разрешается. Тем не менее, язык манипулирования данными (DML) и определение данных операторы языка (DDL) выполняются атомарно.

Тогда приведенный выше код сработает, и вы получите выигрыш в производительности при чтении данных.