39 votes

Comment supprimer un objet d'un modèle Entity Framework sans le charger au préalable ?

Je suis certain d'avoir déjà vu la réponse à cette question quelque part, mais comme je ne l'ai pas trouvée en faisant quelques recherches sur SO ou Google, je la pose à nouveau...

Dans Entity Framework, la seule façon de supprimer un objet de données semble être

MyEntityModel ent = new MyEntityModel();
ent.DeleteObject(theObjectToDelete);
ent.SaveChanges();

Toutefois, cette approche exige que l'objet soit d'abord chargé dans, dans ce cas, le contrôleur, juste pour le supprimer. Existe-t-il un moyen de supprimer un objet métier en ne faisant référence qu'à son ID par exemple ?

S'il existe une manière plus intelligente d'utiliser des expressions Linq ou Lambda, c'est également possible. L'objectif principal, cependant, est d'éviter de charger des données uniquement pour les supprimer.

19voto

John Wigger Points 721

Il est bon de savoir que l'Entity Framework supporte à la fois Linq to Entities et Entity SQL. Si vous souhaitez effectuer des suppressions ou des mises à jour susceptibles d'affecter de nombreux enregistrements, vous pouvez utiliser l'équivalent de ExecuteNonQuery .

En SQL Entity, cela pourrait ressembler à

   Using db As New HelloEfEntities

        Dim qStr = "Delete " & _
                  "FROM Employee"
        db.ExecuteStoreCommand(qStr)
        db.SaveChanges()
    End Using

Dans cet exemple, db est mon ObjectContext . Notez également que le ExecuteStoreCommand prend un tableau facultatif de paramètres.

8voto

Tomas Lycken Points 23432

J'ai trouvé ce poste qui stipule qu'il n'y a pas vraiment de meilleure façon de supprimer des enregistrements. L'explication donnée était que toutes les clés étrangères, les relations, etc. qui sont uniques pour cet enregistrement sont également supprimées, et donc EF doit avoir les informations correctes sur l'enregistrement. Je suis perplexe quant à la raison pour laquelle cela ne pourrait pas être réalisé sans charger les données dans les deux sens, mais comme cela n'arrivera pas très souvent, j'ai décidé (pour l'instant) de ne pas m'en préoccuper.

Si vous avez une solution à ce problème, n'hésitez pas à me le faire savoir =)

4voto

Craig Stuntz Points 95965

Je m'excuse d'avance, mais je dois remettre en question votre objectif.

Si vous supprimez un objet sans jamais le lire, vous ne pouvez pas savoir si un autre utilisateur a modifié l'objet entre le moment où vous avez confirmé que vous vouliez supprimer l'objet et la suppression effective. En "plain old SQL", cela reviendrait à faire :

DELETE FROM FOO
WHERE ID = 1234

Bien sûr, la plupart des gens ne le font pas. A la place, ils font quelque chose comme :

DELETE FROM FOO
WHERE ID = 1234
  AND NAME = ?ExpectedName AND...

L'idée est que la suppression doit échouer (ne rien faire) si un autre utilisateur a modifié l'enregistrement entre-temps.

Avec cette meilleure formulation du problème, il existe deux solutions possibles pour l'utilisation d'Entity Framework.

  1. Dans votre méthode Delete, l'instance existante, compare les valeurs attendues des propriétés, et supprime si elles sont les mêmes. Dans ce cas, l'Entity Framework se chargera d'écrire une instruction DELETE qui inclut les valeurs des propriétés.

  2. Écrivez une procédure stockée qui accepte à la fois l'IDE et les autres valeurs de propriété, et exécutez-la.

4voto

biozinc Points 2760

Il existe un moyen d'usurper le chargement d'une entité en recalculant son EntityKey. Cela ressemble un peu à un hack, mais c'est peut-être le seul moyen de le faire dans EF.

Article de blog sur Suppression sans récupération

3voto

Tymek Points 1305
var toDelete = new MyEntityModel{
    GUID = guid,
    //or ID = id, depending on the key
    };
Db.MyEntityModels.Attach(toDelete);
Db.MyEntityModels.DeleteObject(toDelete);
Db.SaveChanges();

Si votre clé contient plusieurs colonnes, vous devez fournir toutes les valeurs (par exemple GUID, columnX, columnY, etc.).

Jetez également un coup d'œil ici pour une fonction générique si vous avez envie de quelque chose de fantaisiste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X