Les objets de contexte générés par Entity Framework ne sont pas thread-safe.
Que se passe-t-il si j'utilise deux contextes d'entité distincts, un pour chaque thread (et appelle SaveChanges()
sur chacun) - sera-t-il thread-safe?
// this method is called from several threads concurrently
public void IncrementProperty()
{
var context = new MyEntities();
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
Je pense que le contexte de l'entité implémente une sorte de variable 'compteur' qui permet de savoir si les valeurs actuelles dans le contexte sont récentes ou non.
Plusieurs threads opérant sur un seul contexte Entity Framework ne sont pas thread-safe.
Une instance distincte de contexte pour chaque thread est thread-safe. Tant que chaque thread d'exécution aura sa propre instance de contexte EF, tout ira bien.
Dans votre exemple, vous pouvez appeler ce code à partir de plusieurs threads simultanément et chacun travaillera avec plaisir dans son propre contexte.
Cependant, je suggérerais de mettre en place un bloc 'using' pour ceci comme suit:
// this method is called from several threads concurrently
public void IncrementProperty()
{
using (var context = new MyEntities())
{
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
}
Je crois que "SomeObject.SomeIntProperty" est statique. Cela n'a rien à voir avec l'entité étant threadsafe. Si vous écrivez dans des variables statiques dans un environnement multithread, vous devez toujours les envelopper d'un double verrou pour assurer la sécurité des threads.
Vous pouvez utiliser l’approche factory pour injecter votre DbContext en tant qu’usine au lieu d’une instance perse. Jetez un oeil à ceci: https://github.com/vany0114/EF.DbContextFactory
C'est plus sûr et vous évitez de coder en dur la création d'instance dans vos référentiels.
http://elvanydev.com/EF-DbContextFactory/
Il existe une extension à Ninject pour le faire très facilement. Il suffit d'appeler la méthode kernel.AddDbContextFactory<YourContext>();
et vous devez également modifier votre référentiel en recevant un Func<YourContext>