Qual é a melhor prática no EF Core para usar chamadas assíncronas paralelas com um DbContext injetado?

Eu tenho uma API do .NET Core 1.1 com EF Core 1.1 e usando a instalação básica da Microsoft usando o Injection de dependência para fornecer o DbContext aos meus serviços. (Referência:https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro#register-the-context-with-dependency-injection)

Agora, estou olhando para leituras paralelas de banco de dados como uma otimização usandoWhenAll

Então, em vez de:

var result1 = await _dbContext.TableModel1.FirstOrDefaultAsync(x => x.SomeId == AnId);
var result2 = await _dbContext.TableModel2.FirstOrDefaultAsync(x => x.SomeOtherProp == AProp); 

Eu uso:

var repositoryTask1 = _dbContext.TableModel1.FirstOrDefaultAsync(x => x.SomeId == AnId);     
var repositoryTask2 = _dbContext.TableModel2.FirstOrDefaultAsync(x => x.SomeOtherProp == AProp);   
(var result1, var result2) = await (repositoryTask1, repositoryTask2 ).WhenAll();

Tudo está bem, até eu usar a mesma estratégia fora dessas classes de acesso ao repositório de banco de dados e chamar esses mesmos métodos com WhenAll no meu controlador em vários serviços:

var serviceTask1 = _service1.GetSomethingsFromDb(Id);
var serviceTask2 = _service2.GetSomeMoreThingsFromDb(Id);
(var dataForController1, var dataForController2) = await (serviceTask1, serviceTask2).WhenAll();

Agora, quando eu chamo isso do meu controlador, recebo aleatoriamente erros de concorrência como:

System.InvalidOperationException: ExecuteReader requer uma conexão aberta e disponível. O estado atual da conexão está fechado.

A razão pela qual acredito é que, às vezes, esses threads tentam acessar as mesmas tabelas ao mesmo tempo.Eu sei que isso ocorre por design no EF Core e se eu quisesse, poderia criar um novo dbContext toda vez, mas estou tentando ver se há uma solução alternativa. Foi quando eu encontrei este bom post de Mehdi El Gueddari:http://mehdi.me/ambient-dbcontext-in-ef6/

Em que ele reconhece esta limitação:

um DbContext injetado impede que você possa introduzir multi-threading ou qualquer tipo de fluxo de execução paralelo em seus serviços.

E oferece uma solução alternativa personalizada comDbContextScope.

No entanto, ele apresenta uma ressalva mesmo com o DbContextScope, pois ele não funcionará em paralelo (o que estou tentando fazer acima):

se você tentar iniciar várias tarefas paralelas no contexto de um DbContextScope (por exemplo, criando vários threads ou várias tarefas TPL), você terá grandes problemas. Isso ocorre porque o ambiente DbContextScope fluirá por todos os threads que suas tarefas paralelas estão usando.

Seu ponto final aqui me leva à minha pergunta:

Em geral, o acesso paralelo ao banco de dados em uma única transação comercial tem pouco ou nenhum benefício e apenas adiciona complexidade significativa. Qualquer operação paralela executada no contexto de uma transação comercial não deve acessar o banco de dados.

Não devo usar o WhenAll nesse caso nos meus controladores e continuar usando o aguardar um por um? Ou a injeção de dependência do DbContext é o problema mais fundamental aqui; portanto, um novo problema deve ser criado / fornecido a cada momento por algum tipo de fábrica?

questionAnswers(2)

yourAnswerToTheQuestion