6

Я, вероятно, не думаю в правильном направлении. Я довольно новичок в Injection Dependency и ASP.Net Core.DbContext для фоновых задач через инъекцию зависимостей

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

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

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

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

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

+0

Nope: https://stackoverflow.com/questions/3266295/net-entity-framework-and-transactions/3266481#3266481 – Steven

+0

Вы правы, но как бороться с запущенными задачами в другом потоке, которым нужен доступ к DbContext? –

+3

В любом случае это опасный шаблон. Вы не должны использовать приложение ASP.Net для выполнения длительных задач пожарной безопасности и забывания (http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx). Если вы все сделаете правильно, задача выполняется в собственном процессе, и все проблемы с ИС исчезли. –

ответ

10

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

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

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

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

+0

Я не совсем понимаю, как применить его в моем сценарии. У меня есть класс под названием ImportService, который вызывается из контроллера, где я в настоящее время вводя классы репозитория для доступа к базе данных. Я хочу использовать эти классы репозитория в моем методе ProcessImport. Если я правильно понимаю, если я заключить тело метода с использованием (вар сфера = ServiceScopeFactory.CreateScope()) {} будет делать инжектируемые классы последние в течение срока службы блока, или он будет вводить новый экземпляр этих классов? –

+0

Нет, новая область даст вам новый экземпляр классов db (и других сфер действия). Если вы не хотите, чтобы пользователь [запрос] дождался завершения вашего ProcessImport - вам не следует обмениваться экземплярами экземпляра сферы действия. Область запроса удаляется при завершении запроса, в котором размещается все одноразовое содержимое. – Dmitry

3

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

  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, проверка этот блог: «Должен ли я сделать AppDbContext одиночки» http://mehdi.me/ambient-dbcontext-in-ef6/

 Смежные вопросы

  • Нет связанных вопросов^_^