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
Чтобы разбить ваши вопросы:
-
Каков наилучший способ справиться с этой ситуацией?
Это не идеально подходит для API для решения долговременных задач. Вы можете делегировать процесс второму приложению
-
Должен ли я сделать одноэлементное приложение AppDbContext?
DbContext не должен быть singleton в сценарии веб-приложений, поскольку он может создавать проблемы, такие как управление транзакциями.
-
Каков наилучший способ справиться с этой ситуацией?
разбивка различных услуг/процессов:
- API, который возьмет файл. В идеале API должен просто взять файл в качестве ввода и сохранить его на диске или в базе данных.
- Служба, которая будет обрабатывать файл. Создайте этот компонент/службу как отдельную библиотеку. Затем используйте эту библиотеку из консольного приложения. Таким образом вы можете настроить производительность. Сделайте это методом пожара и забывания, сделав его асинхронным методом. Таким образом, у вас есть гибкость в повторном использовании кода.
- Если вы не ожидаете большого количества загрузок файлов, вы можете повторно использовать библиотеку в своем контроллере API и выполнить этот метод с помощью QueueBackgroundWorkItem. См. Здесь для справки: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
-
Должен ли я создать новый экземпляр AppDbContext в методе ProcessImport и передать его?
Поскольку он не является потокобезопасным, создайте и используйте отдельный экземпляр вашего класса dbContext в каждом потоке.
-
Я читал, что DbContext не является потокобезопасным, так что это хороший подход?
Для подробного руководства по использованию EF dbContext ознакомьтесь с этим блогом: http://mehdi.me/ambient-dbcontext-in-ef6/