web-dev-qa-db-fra.com

Sécurité des threads du framework d'entité

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.

  1. Avec le code ci-dessus - appelé à partir de threads distincts - dois-je toujours verrouiller les incrément/savechanges?
  2. Si tel est le cas, quelle est la méthode préférée pour réaliser cela dans ce scénario simple?
31
Harper

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();
   }
}
36
Jim Reineri

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.

0
XtremeBytes

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>