Je ne pense probablement pas dans la bonne direction. Je suis assez nouveau pour Dependency Injection et ASP.Net Core.
J'ai un site Web principal ASP.Net, et l'une des tâches consiste à importer des données d'une feuille Excel vers une base de données qu'un utilisateur téléchargera. Les feuilles Excel peuvent être énormes et les tâches de transformation des données prennent du temps, donc je souhaite les effectuer en arrière-plan. c'est-à-dire que l'utilisateur téléchargera la feuille, la réponse sera envoyée immédiatement et le travail/thread d'arrière-plan importera les données.
J'essaie d'exécuter le travail d'arrière-plan en:
Task.Run(() => ProcessImport(model));
Le problème que je rencontre est que la méthode d'importation de processus appelle les services qui ont des classes de référentiel accédant à AppDbContext via le conteneur d'injection de dépendance ASP.Net qui est ajouté en tant que portée et une fois la réponse renvoyée, le contexte est supprimé. Je reçois une exception d'exécution que vous ne pouvez pas utiliser un contexte après sa suppression.
Ma question est, quelle est la meilleure façon de gérer cette situation? Dois-je faire le singleton AppDbContext? Dois-je créer une nouvelle instance d'AppDbContext dans la méthode ProcessImport et la transmettre? J'ai lu que DbContext n'est pas sûr pour les threads, est-ce donc une bonne approche?
Vous devez passer IServiceScopeFactory
instance (c'est singleton) dans votre tâche.
Dans la tâche interne, lorsque les données arrivent, vous devez créer une nouvelle CreateScope()
et demander des services à partir de cette étendue. Une fois le processus de données terminé - supprimez cette étendue (mais conservez la référence à IServiceScopeFactory
pour la prochaine exécution).
Voir this par exemple. J'exécute des tâches petites et rapides avec cette bibliothèque.
Pour les tâches lourdes/longues, comme l'a écrit Gert, ne comptez pas sur le fait que votre tâche sera toujours exécutée. Soyez prêt pour le redémarrage, soyez prêt pour le retraitement des mêmes données.
Pour décomposer vos questions:
quelle est la meilleure façon de gérer cette situation?
Il n'est pas idéal pour l'API de gérer les tâches de longue durée. Vous pouvez déléguer le processus à une application en arrière-plan
Dois-je faire le singleton AppDbContext?
Le dbContext ne doit pas être singleton dans un scénario d'application Web car il peut poser des problèmes comme la gestion des transactions.
quelle est la meilleure façon de gérer cette situation?
décomposer les différents services/processus:
Dois-je créer une nouvelle instance d'AppDbContext dans la méthode ProcessImport et la transmettre?
Comme il n'est pas adapté aux threads, créez et utilisez une instance distincte de votre classe dbContext dans chaque thread.
J'ai lu que DbContext n'est pas sûr pour les threads, est-ce donc une bonne approche?
Pour un guide détaillé de l'utilisation d'EF dbContext, consultez ce blog: http://mehdi.me/ambient-dbcontext-in-ef6/