TL; DR Comment puis-je utiliser l'application d'entité dans une application d'API de base multithreaded .NET, même si DBContext n'est pas threadsafe?
Je travaille sur une application d'API .Net Core exposant plusieurs interfaces reposantes qui accèdent à la base de données et lisez les données à partir de celui-ci, tout en exécutant plusieurs fois plus de chronométrages, en tant que threads de travail en arrière-plan qui sondent régulièrement des autres Webservices et les stocker dans la base de données.
Je suis conscient du fait que dbcontext n'est pas threadsafe. J'ai lu beaucoup de documents, de poteaux de blogs et de réponses ici sur Stackoverflow, et je pourrais trouver beaucoup de réponses (partiellement contradictoires) pour cela, mais aucune "meilleure pratique" réelle lorsque vous travaillez également avec DI.
En utilisant la valeur par défaut ServiceLifetime.Scoped
via la méthode d'extension AddDbContext
donne des exceptions en raison des conditions de course.
Je ne veux pas travailler avec des serrures (par exemple, sémaphore), car les réciproques évidents sont:
Ne pas injecter MyDbContext
mais DbContextOptions<MyDbContext>
Au lieu de cela, construire le contexte uniquement lorsque j'ai besoin d'accéder à la base de données, à l'aide d'une instruction using
à l'éliminer immédiatement après que la lecture/écriture semble avoir une telle utilisation de la ressource et de nombreuses ouvertures/fermeture de la connexion.
Je suis vraiment perplexe: comment cela peut-il être vrai?
Je ne pense pas que mon usecase est super spécial - peupler la DB à partir d'un ouvrier d'arrière-plan et en l'interrogeant de la couche d'API Web - il devrait donc y avoir un moyen significatif de le faire avec EF Core.
Merci beaucoup!
Une autre approche pour créer son propre dBContextFactory et instancier une nouvelle instance pour chaque requête.
public class DbContextFactory
{
public YourDbContext Create()
{
var options = new DbContextOptionsBuilder<YourDbContext>()
.UseSqlServer(_connectionString)
.Options;
return new YourDbContext(options);
}
}
Usage
public class Service
{
private readonly DbContextFactory _dbContextFactory;
public Service(DbContextFactory dbContextFactory)
=> _dbContextFactory = dbContextFactory;
public void Execute()
{
using (var context = _dbContextFactory.Create())
{
// use context
}
}
}
Avec l'usine, vous n'avez plus besoin de vous inquiéter des slopes et de rendre votre code sans dépendances de base ASP.NET.
[.
[.____] Vous serez toujours confiant sur les données enregistrées lors de l'appelant .SaveChanges()
, où avec Scoped DBContext, il existe des possibilités qu'une entité a été modifiée dans d'autres catégories.