Срок службы в ASP. NET Core - PullRequest
       23

Срок службы в ASP. NET Core

0 голосов
/ 02 февраля 2020

У меня простой вопрос, но я нигде не нашел ответа.

Решение содержит два веб-API. Один -. NET Core 2.1 с EF Core 2.1.1, второй - 3.1 с EF Core 3.1.1, и мой код одинаков для обоих. Существует один пользовательский репозиторий и один контроллер.

Персональный репозиторий:

public PersonRepository(AppContext appContext)
{
   this.appContext = appContext;
}

public async Task<IEnumerable<Person>> GetAll()
{
    return await appContext.People.ToListAsync();
}

Контроллер:

public MyController(PersonRepository personRepository)
{
    this.personRepository = personRepository;
}

[HttpGet]
public async Task<ActionResult> Get()
{
    var data = personRepository.GetAll();
    var data1 = personRepository.GetAll();

    var result = await Task.WhenAll(data, data1);

    return Ok(data.Result);
}
services.AddDbContext<AppContext>(options => options
.UseSqlServer("")
.EnableSensitiveDataLogging(true));

Это может показаться глупостью. Но это только для демонстрации. У меня вопрос, почему этот код работает в решении 2.1, но в 3.1 не , и появляется исключение InvalidOperationException: вторая операция началась в этом контексте до завершения предыдущей операции. (То же самое для IIS и Kestrel).

Я знаю, как это исправить в 3.1, это не мой вопрос. Мне просто нужно знать, почему это произошло и что изменилось между этими версиями или когда-либо.

Большое спасибо за любой ответ.

1 Ответ

0 голосов
/ 03 февраля 2020

Если вы действительно хотите запустить оба запроса параллельно, вам потребуется два DbContext с, поскольку DbContext не является потокобезопасным.

Вам необходимо изменить способ регистрации DbContext в вашем сервисном контейнере для этого:

 services.AddDbContext<AppDbContext>(options => options
            .UseSqlServer("")
            .EnableSensitiveDataLogging(true), 
            ServiceLifetime.Transient);

Добавьте возможность зависимости для создания нового экземпляра DbContext (простая фабрика):

services.AddTransient<Func<AppDbContext>>(provider => provider.GetRequiredService<AppDbContext>);

и измените свою зависимость соответственно:

public PersonRepository(Func<AppContext> appContextFactory)
{
    this.appContextFactory = appContextFactory;
}

public async Task<IEnumerable<Person>> GetAll()
{
   using (var appContext = appContextFactory())
   {
       return await appContext.People.ToListAsync();
   }
}

Помните, что изменение области действия времени жизни на Transient означает, что если вы введете DbContext в нескольких классах в рамках одного запроса, вы не получите тот же DbContext экземпляр. Используйте с осторожностью.

...