2

J'ai le code pseduo suivant dans certains projets Repository Pattern qui utilise EF4.Comment dois-je gérer cette erreur Optimistic Concurrency dans ce code Entity Framework, j'ai?

public void Delete(int someId) 
{ 
    // 1. Load the entity for that Id. If there is none, then null. 
    // 2. If entity != null, then DeleteObject(..); 
} 

assez simple, mais je reçois une erreur d'exécution: -

ConcurrencyException: Store, Update, Insert or Delete statement affected an unexpected number of rows (0).

Maintenant, voici ce qui se passe: -

  1. Deux instances de EF4 sont en cours d'exécution INTHE application en même temps.
  2. Instance A appelle la suppression.
  3. Les appels d'instance B suppriment une nano seconde plus tard.
  4. L'instance A charge l'entité.
  5. L'instance B charge également l'entité. L'instance A supprime maintenant cette entité - les bananes froides.
  6. L'instance B tente de supprimer l'entité, mais elle est déjà supprimée. En tant que tel, le no-count ou quoi ne pas 0, quand il attendait 1 .. ou quelque chose comme ça. Fondamentalement, il a compris que l'élément qu'il est censé supprimer, n'a pas supprimé (parce qu'il est arrivé il ya une fraction de seconde).

Je ne sais pas si c'est comme un course-condition ou quelque chose.

De toute façon, y a-t-il des trucs que je peux faire ici pour que le 2ème appel ne plante pas? Je pourrait en faire une procédure stockée .. mais j'espère éviter cela maintenant.

Des idées? Je me demande s'il est possible de verrouiller cette ligne (et cette ligne seulement) quand la sélection est appelée ... forçant l'instance B à attendre que le verrou de ligne ait été relâché. À ce moment-là, la ligne est supprimée, donc quand l'instance B est sélectionnée, les données ne sont pas là ... donc elle ne sera jamais supprimée.

+0

Pourquoi ne pas simplement gérer l'exception de concurrence? Si l'objet a été supprimé d'un autre thread (alias l'instance EF), aucun travail ne reste pour ce thread puisque l'enregistrement a déjà été supprimé. –

+0

C'est le problème -> les deux instances pensent avoir un objet à supprimer, car ils lisent tous les deux à partir de la BD en même temps. C'est juste que l'instance A complète la méthode DeleteObject (..) une nano seconde avant le second appel .. pour le même objet. Maintenant, je gère l'exception .. mais je me sens comme c'est éviter le vrai problème .. et je me demande si elle pourrait être traitée avec un verrouillage ou quelque chose? –

Répondre

0

Normalement, vous devriez attraper le OptimisticConcurrencyException et ensuite gérer le problème d'une manière qui a du sens pour votre modèle d'affaires - puis appelez à nouveau SaveChanges.

try 
{ 
    myContext.SaveChanges(); 
} 
catch (OptimisticConcurrencyException e) 
{ 
    if (e.StateEntries.FirstOrDefault() is DeletingObject) 
     myContext.Detach(e.StateEntries.First(); 
    myContext.SaveChanges(); 
} 

Donnez qu'un tourbillon et voir comment vous allez - pas testé/compilé ou quoi que ce soit - je l'ai utilisé DeletingObject comme le type de l'entité que vous essayez de supprimer. Substituer pour votre type d'entité.

+0

Hmm - intéressant. Pouvez-vous réellement expliquer ce que vous essayez de faire dans la capture? Donc, avec mon exemple initial, si Instance_B fait la suppression .. et il jette l'exception .. puis votre essayant de voir se détacher .. l'objet supprimé (parce qu'il ne devrait pas être là? –

+0

En détachant l'objet qui a déjà été supprimé, j'essaye d'empêcher le gestionnaire d'état de pousser cette opération de suppression vers la base de données. Un objet qui doit être supprimé est toujours attaché, il a un état d'entité de supprimé. Je viens de lancer un test rapide et d'appeler .DeleteObject (myObject) suivi de .Detach (myObject) suivi de .SaveChanges() ne pousse pas la suppression. Donnez-lui un go mate et voir si cela aide. –

+0

Est-ce que cela a résolu votre problème? –

Questions connexes