DbContext для фоновых задач через Injection Dependency

Я, вероятно, не думаю в правильном направлении. Я новичок в Injection Dependency и ASP.Net Core.

У меня есть основной веб-сайт ASP.Net, и одной из задач является импорт данных из листа excel в базу данных, которую пользователь будет загружать. Листы Excel могут быть огромными, а задачи преобразования данных - это время, поэтому я хочу выполнить их в фоновом режиме. т.е. пользователь загрузит лист, ответ будет отправлен немедленно, а фоновое задание/поток импортирует данные.

Я пытаюсь запустить фоновое задание:

Task.Run(() => ProcessImport(model));

Проблема, с которой я сталкиваюсь, заключается в том, что метод импорта процессов вызывает службы, имеющие классы репозитория, которые получают доступ к AppDbContext через контейнер для инъекций зависимостей ASP.Net, который добавляется как область действия, и как только ответ отправляется обратно, контекст удаляется. Я получаю исключение во время выполнения, которое вы не можете использовать контекст после его расположения.

Мой вопрос: каков наилучший способ справиться с этой ситуацией? Должен ли я сделать одноэлементное приложение AppDbContext? Должен ли я создать новый экземпляр AppDbContext в методе ProcessImport и передать его? Я читал, что DbContext не является потокобезопасным, так что это хороший подход?

Ответ 1

Вы должны передать экземпляр IServiceScopeFactory (это singleton) в свою задачу.

Внутри задачи, когда поступают данные, вы должны создать новый CreateScope() и запросить службы из этой области. Когда процесс обработки данных заканчивается - удалите эту область (но держите ссылку на IServiceScopeFactory для следующего запуска).

См. Это, например. Я выполняю небольшие и быстрые задачи с этой библиотекой.

Для тяжелых/длительных задач, как писал Герт, не полагайтесь на то, что ваша задача всегда будет завершена. Будьте готовы к перезапуску, будьте готовы к повторной обработке одних и тех же данных.

Ответ 2

Чтобы разбить ваши вопросы:

  1. Каков наилучший способ справиться с этой ситуацией?

    Это не идеально подходит для API для решения долговременных задач. Вы можете делегировать процесс второму приложению

  2. Должен ли я сделать одноэлементное приложение AppDbContext?

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

  3. Каков наилучший способ справиться с этой ситуацией?

    разбивка различных услуг/процессов:

    • API, который возьмет файл. В идеале API должен просто взять файл в качестве ввода и сохранить его на диске или в базе данных.
    • Служба, которая будет обрабатывать файл. Создайте этот компонент/службу как отдельную библиотеку. Затем используйте эту библиотеку из консольного приложения. Таким образом вы можете настроить производительность. Сделайте это методом пожара и забывания, сделав его асинхронным методом. Таким образом, у вас есть гибкость в повторном использовании кода.
    • Если вы не ожидаете большого количества загрузок файлов, вы можете повторно использовать библиотеку в своем контроллере API и выполнить этот метод с помощью QueueBackgroundWorkItem. См. Здесь для справки: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
  4. Должен ли я создать новый экземпляр AppDbContext в методе ProcessImport и передать его?

    Поскольку он не является потокобезопасным, создайте и используйте отдельный экземпляр вашего класса dbContext в каждом потоке.

  5. Я читал, что DbContext не является потокобезопасным, так что это хороший подход?

    Для подробного руководства по использованию EF dbContext ознакомьтесь с этим блогом: http://mehdi.me/ambient-dbcontext-in-ef6/