1

J'utilise Mssql comme db et EF4 comme ORM/DAL.
Ma question concerne le code suivant:Dois-je vérifier si une ligne existe avant la suppression?

public static void DeleteBuilding(int buildingId, int countryId) 
{ 
    PlayerBuilding playerBuilding = new PlayerBuilding() 
    { 
     CountryID = countryId, 
     BuildingID = buildingId 
    }; 
    Entities.PlayerBuildings.Attach(playerBuilding); 
    Entities.PlayerBuildings.DeleteObject(playerBuilding); 
    Entities.SaveChanges(); 
} 

Si la ligne existe cela fonctionne très bien, sinon je reçois une exception (mise à jour Store, insertion ou de suppression affecté un nombre inattendu de lignes . (0) les entités peuvent avoir été modifiés ou supprimés car les entités ont été chargées Actualisez entrées ObjectStateManager)
Dois-je faire un aller-retour à la base de données pour vérifier si la ligne existe comme ceci:..

public static void DeleteBuilding(int buildingId, int countryId) 
{ 
    PlayerBuilding playerBuilding = (from p in Entities.PlayerBuildings 
            where p.BuildingID == buildingId && p.CountryID == countryId 
            select p).FirstOrDefault(); 
    if (playerBuilding != null) 
    { 
     Entities.PlayerBuildings.DeleteObject(playerBuilding); 
     Entities.SaveChanges(); 
    } 
} 

Je pense que l'aller-retour supplémentaire est un peu inutile car sans l'EF, avec SQL pur je pourrais simplement supprimer la ligne avec une seule commande DELETE.

Quelle serait une meilleure pratique?

Répondre

0

Cette erreur est un effet secondaire de la concurrence optimiste d'Entity Framework. Fondamentalement, quelqu'un d'autre a peut-être supprimé l'enregistrement entre vous l'avoir récupéré. Ou peut-être que vous avez fait quelque chose avec l'entité avant ce code. Essayez de l'exécuter dans un environnement isolé (par exemple un test unitaire) pour voir si le problème persiste.

Oui, vous pourriez jouer en toute sécurité et obtenir à nouveau l'enregistrement, ou vous pouvez utiliser ObjectContext.Refresh:

public static void DeleteBuilding(int buildingId, int countryId) 
{ 
    PlayerBuilding playerBuilding = new PlayerBuilding() 
    { 
     CountryID = countryId, 
     BuildingID = buildingId 
    }; 

    try 
    { 
     Entities.PlayerBuildings.Attach(playerBuilding); 
     Entities.PlayerBuildings.DeleteObject(playerBuilding); 
     Entities.SaveChanges(); 
    } 
    catch (OptimisticConcurrencyException) 
    { 
     Entities.Refresh(RefreshMode.ClientWins, playerBuilding); 
     Entities.SaveChanges(); 
    } 
} 

Sur une note côté - peut-être est parce que votre méthode est statique? Comment instanciez-vous votre contexte? J'espère que vous n'utilisez pas un singleton. :(

Il y a une excellente article sur EF optimiste here concurrency, ce qui explique plus en détail pourquoi votre obtenir cette erreur, et quelles mesures peuvent être prises pour le contrer.

+0

merci pour le commentaire RPM, mais il ne s'agit pas d'un problème de simultanéité optimiste: je travaille sur un ordinateur développeur local, je ne tente pas la méthode statique, pas le problème non plus, le contexte est instancié à l'aide de cette méthode: http://dotnetslackers.com/articles/ado_net/Managing -Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx., En utilisant la méthode normale pour instancier le contexte ne changeant rien – Adir

+0

Jetez un oeil à l'article - l'erreur dans cet arti Clé est exactement le même que le vôtre. Avez-vous essayé d'exécuter le code ci-dessus dans un test unitaire (isolé)? Aussi - De quelle façon dans cet article vous instanciez-vous le contexte? (Il existe plusieurs méthodes dans cet article) – RPM1984

+0

J'ai utilisé la méthode UnitOfWorkScope mais ce n'est pas le problème. Même si j'instancie le contexte en utilisant l'ancienne méthode (MyContext context = new MyContext()), la même erreur persiste. Je ne pense pas que cela soit lié à la concurrence, l'erreur est montrée parce que j'essaye de supprimer un objet qui n'existe pas dans le contexte. – Adir