IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entity Framework Discussion :

Comment supprimer des données dans deux Entités (Tables) qui sont liées


Sujet :

Entity Framework

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 164
    Points : 88
    Points
    88
    Par défaut Comment supprimer des données dans deux Entités (Tables) qui sont liées
    Bonjour à tous

    J'ai une table "User" et une table "Proximity" (Une capture d’écran de mon model EDMX pour mieux voir les colonnes de chaque table ainsi leurs relations)

    Question

    Pourquoi cette méthode supprime juste les utilisateurs associé à la table "Proximity" et PAS aussi dans la table "User" sachant que y a un lien entre les deux tables que je fais dans le code avec Include ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
     public static void DeleteUser_Proximity(int prxIdx)
            {
                try
                {
                    using (EDM edm = new EDM())
                    {
                        Proximity proximity = edm.Proximity.Include("User").Where(p => p.PrxIdx == prxIdx).FirstOrDefault();
                        if (proximity != null)
                        {
                            while (proximity.User.Count > 0)
                            {
                                User user = proximity.User.First();
                                proximity.User.Remove(user);
                            }
                        }
                        edm.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    Logging.Log(ex);
                    throw;
                }
            }
    Ce que je veux moi c'est que quand je supprime un User dans la table Proximity il sera supprimé aussi dans la Table "User"

    Ps: ma source de donnée est SQL SERVER 2008

    Merci à tous
    Images attachées Images attachées  

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur Full-stack
    Inscrit en
    Novembre 2010
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Full-stack

    Informations forums :
    Inscription : Novembre 2010
    Messages : 372
    Points : 489
    Points
    489
    Par défaut
    Citation Envoyé par jérémyp8 Voir le message
    Bonjour à tous

    J'ai une table "User" et une table "Proximity" (Une capture d’écran de mon model EDMX pour mieux voir les colonnes de chaque table ainsi leurs relations)

    Question

    Pourquoi cette méthode supprime juste les utilisateurs associé à la table "Proximity" et PAS aussi dans la table "User" sachant que y a un lien entre les deux tables que je fais dans le code avec Include ?

    Ce que je veux moi c'est que quand je supprime un User dans la table Proximity il sera supprimé aussi dans la Table "User"

    Ps: ma source de donnée est SQL SERVER 2008

    Merci à tous
    Bonjour,

    Il te faudra activer les "delete cascade" dans ta Base de Données, n'oublie de le faire pour les Update aussi."

    Cordialement.
    La recherche de la connaissance est une Lumière qui apaise le Cœur.
    Si une réponse vous a été utile , n'oubliez pas de voter en cliquant sur:.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 164
    Points : 88
    Points
    88
    Par défaut
    Bonjour Alexandre le Grand

    Grace à tes conseils, j'ai pu régler mon problème

    Merci énormément

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Attention avec les opérations en Cascade car même en-dehors d'Entity Framework ce comportement sera présent (ca peut créer de mauvaises surprises en production lorsqu'on a oublié ce détail, et Dieu sait qu'on a vite fait de l'oublier) : "tiens je vais supprimer des infos dans cette table ... ah ben mince une partie de mes campagnes a aussi disparu ..."

    Et puis bien sûr le dernier backup remonte à plusieurs jours voire semaines, quand il y en a un...

    My 2 cents
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 164
    Points : 88
    Points
    88
    Par défaut
    Merci énormément pour tes conseils DotNetMatt

  6. #6
    Membre expérimenté Avatar de dfiad77pro
    Homme Profil pro
    Responsable Architecture logicielle
    Inscrit en
    Décembre 2008
    Messages
    541
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable Architecture logicielle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 541
    Points : 1 729
    Points
    1 729
    Par défaut
    Citation Envoyé par DotNetMatt Voir le message
    Attention avec les opérations en Cascade car même en-dehors d'Entity Framework ce comportement sera présent (ca peut créer de mauvaises surprises en production lorsqu'on a oublié ce détail, et Dieu sait qu'on a vite fait de l'oublier) : "tiens je vais supprimer des infos dans cette table ... ah ben mince une partie de mes campagnes a aussi disparu ..."

    Et puis bien sûr le dernier backup remonte à plusieurs jours voire semaines, quand il y en a un...

    My 2 cents
    Oui, sans compter les problèmes de performance avec EF, si tu lance un delete sur 10 000 lignes

  7. #7
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 164
    Points : 88
    Points
    88
    Par défaut
    Donc si je comprends bien cette pratique "les opérations en Cascade" ont plus d’inconvenants que d'avantages !

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur Full-stack
    Inscrit en
    Novembre 2010
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Full-stack

    Informations forums :
    Inscription : Novembre 2010
    Messages : 372
    Points : 489
    Points
    489
    Par défaut
    Perso, je ne comprends pas trop ce qu'ils disent. Pour des tables liées par une clé étrangère, lorsqu'on efface une clé, il faudrait aussi effacer les colonnes de clé(s) étrangère(s) liée à celle ci. Sur SQL SERVER, ça évite les messages d'erreurs.
    La recherche de la connaissance est une Lumière qui apaise le Cœur.
    Si une réponse vous a été utile , n'oubliez pas de voter en cliquant sur:.

  9. #9
    Membre expérimenté Avatar de dfiad77pro
    Homme Profil pro
    Responsable Architecture logicielle
    Inscrit en
    Décembre 2008
    Messages
    541
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable Architecture logicielle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 541
    Points : 1 729
    Points
    1 729
    Par défaut
    En fait si la fonction de cascade est super pratique niveau codage.
    Sur les grosses bases de production, on évite cela, on préfère maîtriser la suppression via des proc stockées, pour des raisons de maintenance et d'optimisations.

    en gros si t'a 100 000 000 de lignes ( avec 2-3 liaisons) ça peut te prendre plus 20h pour supprimer en cascades , et le calcul asynchrone des indexes fait monter en flèche la charge de la base.

    Enfin je parle surtout sur ORACLE, mais je suppose que ça doit être pareil sur SQL Server, surtout avec l'Entity framework.


    Bref, sur un projet perso tu peut l'utiliser sans soucis, mais en entreprise , sur des bases de moyenne à forte volumétrie, je le dé-conseil fortement.

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur Full-stack
    Inscrit en
    Novembre 2010
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Full-stack

    Informations forums :
    Inscription : Novembre 2010
    Messages : 372
    Points : 489
    Points
    489
    Par défaut
    Merci pour l'éclaircissement.

    cordialement.
    La recherche de la connaissance est une Lumière qui apaise le Cœur.
    Si une réponse vous a été utile , n'oubliez pas de voter en cliquant sur:.

  11. #11
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par dfiad77pro Voir le message
    Enfin je parle surtout sur ORACLE, mais je suppose que ça doit être pareil sur SQL Server, surtout avec l'Entity framework.
    Oui c'est pareil sur tout SGBDR disposant de cette fonctionnalité, peu importe qu'on utilise Entity Framework ou non. Et le pire, c'est si la clé étrangère n'est pas indexée, alors c'est full scan sur toute la table pour trouver les enregistrements à supprimer, puis suppression. Ca peut faire mal
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  12. #12
    Membre expérimenté Avatar de dfiad77pro
    Homme Profil pro
    Responsable Architecture logicielle
    Inscrit en
    Décembre 2008
    Messages
    541
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable Architecture logicielle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 541
    Points : 1 729
    Points
    1 729
    Par défaut
    Citation Envoyé par DotNetMatt Voir le message
    Oui c'est pareil sur tout SGBDR disposant de cette fonctionnalité, peu importe qu'on utilise Entity Framework ou non. Et le pire, c'est si la clé étrangère n'est pas indexée, alors c'est full scan sur toute la table pour trouver les enregistrements à supprimer, puis suppression. Ca peut faire mal
    Quand j'ai débuté avec EF (époque du 4) il balançait une requête par delete donc ça faisait encore plus mal
    C'est toujours le cas mais bon c'est justifié,
    il y'a plein de raisons pour lesquelles ils n'ont pas encore pris la décision d'implémenter le Batch Delete/update ( y'a tout de même un sujet de travail en cours pour EF7 il me semble).

  13. #13
    Membre confirmé
    Homme Profil pro
    Développeur Full-stack
    Inscrit en
    Novembre 2010
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Full-stack

    Informations forums :
    Inscription : Novembre 2010
    Messages : 372
    Points : 489
    Points
    489
    Par défaut
    Pourrais-je avoir un exemple de procédure delete pour de grandes bases de productions. Je compte insérer pas moins de 1,4 millions de données dans une table lors des tests. J'ai utilisé EF pour l'application que je développe actuellement.
    La recherche de la connaissance est une Lumière qui apaise le Cœur.
    Si une réponse vous a été utile , n'oubliez pas de voter en cliquant sur:.

  14. #14
    Membre expérimenté Avatar de dfiad77pro
    Homme Profil pro
    Responsable Architecture logicielle
    Inscrit en
    Décembre 2008
    Messages
    541
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable Architecture logicielle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 541
    Points : 1 729
    Points
    1 729
    Par défaut
    Tu ne peut pas insérer 1 millions de lignes directement avec EF, c'est bien trop long et très gourmand en mémoire,
    personnellement, je limite à une centaine de lignes ( sur les applications non critiques)

    si tu ne peut/veut pas faire ça en procédure stockée, la solution (C#) suivante peut s'appliquer.
    Avec cette solution on arrive grosso-modo 100 000 lignes par secondes sur une table de 10 colonnes et 3 indexes ( estimation à la louche )

    Note : j'écris pour oracle , mais avec SQL Server la SYNTAXE varie peu ( @ pour les bind).
    C'est sensiblement plus simple pour les deletes, mais j'ai préféré mettre un exemple d'insert

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
            /// <summary>
            /// insère une ligne composée de listes en base
            /// (note mieux vaut utiliser un vrai objet en paramètre)
            /// </summary>
            /// <param name="cols1">colonne 1</param>
            /// <param name="cols2">colonne 2</param>
      public static void INSERT(List<int> cols1, List<decimal> cols2)
            {
      using (var connexion = new OracleConnection()) // changer le provider dans le cadre SQL_SERVER
                {
                    string sql = "INSERT INTO TABLE (COL1,COL2 ) VALUES (:VAL_COL1,:VAL_COL2)";
     
                    connexion.Open();
     
                    OracleCommand cmd = connexion.CreateCommand(); // changer l'objet de commande dans le cadre SQL_SERVER
                    cmd.CommandText = sql;
                    cmd.CommandType = CommandType.Text;
                    cmd.BindByName = true;
                    cmd.ArrayBindCount = cols1.Count; // on compte le nombre de ligne à insérer
     
                    // Binding des valeurs des lignes à insérer
                    cmd.Parameters.Add(":VAL_COL1", OracleDbType.Int32, cols1.ToArray(), ParameterDirection.Input);
                    cmd.Parameters.Add(":VAL_COL2", OracleDbType.Decimal, cols2.ToArray(), ParameterDirection.Input);             
     
                    try
                    {
                        cmd.ExecuteNonQuery();
                      //  CustomLogs.Write(cmd.ArrayBindCount + " BulkInserts  réussi");
                    }
                    catch
                    {
                       //  CustomLogs.Write(cmd.ArrayBindCount + " [ERREUR] BulkInserts  ratés");
                    }
     
                    connexion.Close();
                }
    }

    Bon j'ai écris ça très vite, ce n'est pas parfait et paternisé mais ça peut débloquer.
    Attention à ne pas envoyer des listes de 1 000 000 de valeurs en une seul fois, il faut envoyer par blocs.


    dans le cadre du delete , Tu vide les tables dans leur ordre Hiérarchique :
    Petit Fils -->Fils --> Parent , soit 3 requêtes ou le tout dans une proc stockée

    au cas ou un peu d'oracle :

    Code PL/SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
       PROCEDURE delete_table_test (p_SEQ  IN NUMBER, p_commit  IN VARCHAR2)
       IS
       BEGIN
          -- On efface du fils au parent
          DELETE FROM PETIT_FILS
                WHERE SEQ = p_SEQ;
     
          DELETE FROM FILS
                WHERE SEQF = p_SEQ;
     
          DELETE FROM PERE
                WHERE SEQ= p_SEQ;
     
     
          IF (p_commit = 'O')
          THEN
             COMMIT;
          END IF;
       END delete_table_test ;



    ensuite il y a plusieurs solutions de Tuning :
    - si c'est une table entière : il faut utiliser les fonctions de vidage de table (TRUNCATE,ETC)
    - si c'est plusieurs millions de lignes, on peut désactiver l'indexation et la recalculer plus tard (à voir avec un DBA)
    - bref y'a plein de petits trucs à étudier pour trouver la solution adaptée


    Important :
    - pense à détacher les entités liées ou à utiliser un AsNoTracking() avant de charger les éléments concernés (si tu le peux, dans ton contexte), sinon t'aura une exception de Désynchronisation du contexte.
    - J'ai conscience que faire du SQL avec entity c'est chiant et moche, mais pour les opérations en masse , il n'y a pas le choix.

  15. #15
    Membre confirmé
    Homme Profil pro
    Développeur Full-stack
    Inscrit en
    Novembre 2010
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Full-stack

    Informations forums :
    Inscription : Novembre 2010
    Messages : 372
    Points : 489
    Points
    489
    Par défaut
    Pour les insertions de masse , je le fais depuis la base de données SQL SERVER, seulement pour les delete que je souhaiterais tester sur EF.
    Merci pour le partage.

    Cordialement.
    La recherche de la connaissance est une Lumière qui apaise le Cœur.
    Si une réponse vous a été utile , n'oubliez pas de voter en cliquant sur:.

  16. #16
    Membre expérimenté Avatar de dfiad77pro
    Homme Profil pro
    Responsable Architecture logicielle
    Inscrit en
    Décembre 2008
    Messages
    541
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable Architecture logicielle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 541
    Points : 1 729
    Points
    1 729
    Par défaut
    ok 1 dernier bout de code alors :

    1) détacher une liste d'entitée sur EF 5,6 (DbContext)
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      foreach (ENTIY e in listEntityTracked)
                {
                    context.Entry(e).State = EntityState.Detached;
                }
     
                //Appel de la proc stocké


    Après pour SQL server il existe des librairies d'extension pour gérer les batch DELETE, mais comme ça marche pas avec oracle, je ne les utilises pas..

    https://github.com/loresoft/EntityFramework.Extended
    https://www.nuget.org/packages/EntityFramework.Extended

Discussions similaires

  1. Comment supprimer des enregistrements dans deux tables ?
    Par Daniela dans le forum VBA Access
    Réponses: 15
    Dernier message: 18/06/2009, 17h51
  2. comment importer des données dans une table paradox
    Par pierrot67 dans le forum Bases de données
    Réponses: 6
    Dernier message: 02/08/2007, 18h32
  3. supprimer des données dans plusieurs tables
    Par mnssylvain dans le forum Access
    Réponses: 4
    Dernier message: 28/01/2007, 19h06
  4. [VB.Net] Comment insérer des données dans des tables ?
    Par shakoulé dans le forum Accès aux données
    Réponses: 2
    Dernier message: 23/09/2006, 21h46
  5. [DisplayTag] Comment affecter des données dans la table ?
    Par MAJIK_ENIS dans le forum Taglibs
    Réponses: 7
    Dernier message: 04/04/2006, 15h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo