web-dev-qa-db-fra.com

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

Je suis sûr d'avoir vu la réponse à cette question quelque part, mais comme je ne l'ai pas trouvée avec quelques recherches sur SO ou google, je la pose de nouveau quand même ...

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();

Cependant, cette approche nécessite que l'objet soit chargé dans, dans ce cas, le contrôleur d'abord, juste pour le supprimer. Existe-t-il un moyen de supprimer un objet métier référençant uniquement par exemple son ID?

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

39
Tomas Aschan

Il convient de savoir que Entity Framework prend en charge à 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.

Dans Entity SQL, 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 la fonction ExecuteStoreCommand prend un tableau facultatif de paramètres.

19
John Wigger

J'ai trouvé ce message , qui indique qu'il n'y a vraiment pas de meilleur moyen de supprimer des enregistrements. L'explication donnée était que toutes les clés étrangères, relations, etc. qui sont uniques pour cet enregistrement sont également supprimées, et EF doit donc avoir les informations correctes sur l'enregistrement. Je suis perplexe de savoir pourquoi cela ne pourrait pas être réalisé sans charger les données d'avant en arrière, mais comme cela ne se produira pas très souvent, j'ai décidé (pour l'instant) que je ne m'embêterai pas.

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

8
Tomas Aschan

Il existe un moyen d'usurper le chargement d'une entité en recalculant sa EntityKey. Cela ressemble à un peu de piratage, mais pourrait être le seul moyen de le faire dans EF.

Article de blog sur Suppression sans récupération

4
biozinc

Vous pouvez créer un objet avec le même identifiant et le transmettre à la suppression MAIS c'est bon pour les objets simples si vous avez des relations complexes dont vous pourriez avoir besoin de plus que cela

                var user = new User { ID = 15 };
                context.Entry(user).State = EntityState.Deleted;
                context.SaveChanges();
4
CMS

Toutes mes excuses à l'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 réelle. Dans "plain old SQL", ce serait comme faire:

DELETE FROM FOO
WHERE ID = 1234

Bien sûr, la plupart des gens ne font pas cela. Au lieu de cela, ils font quelque chose comme:

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

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

Avec cela, une meilleure déclaration du problème, il existe deux solutions possibles lors de l'utilisation de l'Entity Framework.

  1. Dans votre méthode Delete, l'instance existante, comparez les valeurs attendues des propriétés et supprimez si elles sont identiques. Dans ce cas, 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 le IDE et les autres valeurs de propriété, et exécutez-le.

4
Craig Stuntz

Avec Entity Framework 5, il y a Entity Framework Extended Library . Disponible sur NuGet. Ensuite, vous pouvez écrire quelque chose comme:

context.Users.Delete(u => u.Id == id);

Il est également utile pour les suppressions en masse.

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

Dans le cas où votre clé contient plusieurs colonnes, vous devez fournir toutes les valeurs (par exemple GUID, columnX, columnY, etc.).

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

3
tymtam