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

NHibernate Discussion :

NHibernate et la suppression des objets enfant


Sujet :

NHibernate

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut NHibernate et la suppression des objets enfant
    Bonjour,

    Cela fait maintenant 2 semaines que je dois refaire toute la couche de données d'un projet en utilisant NHibernate.

    Sur les objets "simple" je n'ai aucuns problèmes et à priori toutes mes actions fonctionnaient aussi sur des hiérarchies d'objets (des objets qui contiennent des collections d'objets).
    Seulement voilà, je me suis aperçut d'un "petit" souci :
    Quand je supprime un objet "Enfant" de la collection d'un objet "Parent" et que je sauvegarde l'objet parent, NHibernate ne fait que supprimer la clef étrangère de l'objet "Enfant" en base de données...

    Effectivement les objets ne remontent plus via les méthodes de sélections de NHibernate mais à mon avis ce ne doit pas être le comportement normal .

    Voilà à qui ressemble le mapping de mes classes "Parent" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="MaDLL"
                       namespace="MaDLL.Entities">
    <class name="MaDLL.Entities.Parent" table="Parent">
    <id>…</id>
     <bag name="Enfants" cascade="all-delete-orphan" >
          <key column="idParent"/>
          <one-to-many class="MaDLL.Entities.Enfant"/>
      </bag>
    </class>
    </hibernate-mapping>
    Et celui de mes classes « Enfant » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="MaDLL"
                       namespace="MaDLL.Entities">
    <class name="MaDLL.Entities. Enfant  " table=" Enfant  ">
    	<id>…</id>
        <property name="Nom" column="nom" />
        <property name="Prenom" column="prenom" />
    </class>
    </hibernate-mapping>
    Pour ce qui est du code utilisé pour la sauvegarde :

    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
    public void Sauvegarder(T element)
            {
                StartTransaction();
     
                try
                {
                    Session.SaveOrUpdate(element);
                    Session.Flush();
     
                    CommitTransaction();
                }
                catch (Exception ex)
                {
                    RollBacktTransaction();
                    throw ex;
                }
            }
    Donc voilà si quelqu’un voit comme ça la boullette qui doit être énorme j’imagine, ça m’interresse car je m’arrache les cheveux là :p

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par Philenain Voir le message
    Quand je supprime un objet "Enfant" de la collection d'un objet "Parent" et que je sauvegarde l'objet parent, NHibernate ne fait que supprimer la clef étrangère de l'objet "Enfant" en base de données...
    Ca me semble normal : en enlevant l'enfant de la collection du parent, tu ne dis pas "supprime l'objet enfant", mais "dissocie l'enfant du parent". Tu pourrais vouloir l'ajouter ultérieurement à un autre parent, ce qui ne serait pas possible s'il avait été supprimé

    Citation Envoyé par Philenain Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
                catch (Exception ex)
                {
                    RollBacktTransaction();
                    throw ex;
                }
    Argh...
    Il faut jamais faire "throw ex", mais juste "throw", sinon tu réinitialises la pile de l'exception et tu ne sais plus d'où elle vient au départ. Par contre tu peux aussi "l'envelopper" dans une autre exception en tant que InnerException :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    throw new ApplicationException("Erreur lors de la mise à jour", ex);
    Citation Envoyé par Philenain Voir le message
    Donc voilà si quelqu’un voit comme ça la boullette qui doit être énorme j’imagine, ça m’interresse car je m’arrache les cheveux là :p
    Y a pas de boulette... comme je l'ai dit plus haut, ce comportement est normal

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Dabord merci de ta réponse

    Oui c'est vrai qu'en y repenssant c'est logique en effet.

    Pour le "throw ex" j'utilise d'habitude une exception personalisée, mais, ayant l'interdiction de transmettre le moindre bout de code de l'application à l'extérieur, j'ai dût retaper vite fait un exemple et celà m'a échappé .

    Don encore merci pour ta réponse et bonne continuation

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 273
    Points : 2 203
    Points
    2 203
    Par défaut
    Citation Envoyé par Philenain Voir le message
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="MaDLL"
                       namespace="MaDLL.Entities">
    <class name="MaDLL.Entities.Parent" table="Parent">
    <id>…</id>
     <bag name="Enfants" cascade="all-delete-orphan" >
          <key column="idParent"/>
          <one-to-many class="MaDLL.Entities.Enfant"/>
      </bag>
    </class>
    </hibernate-mapping>
    Et celui de mes classes « Enfant » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="MaDLL"
                       namespace="MaDLL.Entities">
    <class name="MaDLL.Entities. Enfant  " table=" Enfant  ">
    	<id>…</id>
        <property name="Nom" column="nom" />
        <property name="Prenom" column="prenom" />
    </class>
    </hibernate-mapping>
    Pour ce qui est du code utilisé pour la sauvegarde :

    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
    public void Sauvegarder(T element)
            {
                StartTransaction();
    
                try
                {
                    Session.SaveOrUpdate(element);
                    Session.Flush();
    
                    CommitTransaction(); 
               }
                catch (Exception ex)
                {
                    RollBacktTransaction();
                    throw ex;
                }
            }
    Oui c'est normal, mais, je ne comprends pas ce que le session.Flush() vient faire au milieu d'une transaction.
    Tu peux le supprimer, ça t'évitera de mettre une bombe à retardement dans ton code.

    Dans la même veine, tu peux aussi logger le SQL en utilisant l'option showsql, et regarder le sql généré par ton update.

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    D'abord merci pour ta réponse,

    Le coup du session.flush() c'est un reste d'un bout de code que j'avais tenté pour résoudre un soucis que j'ai eu, et que j'ai toujours d'ailleurs, avec NHibernate.

    En fait: j'ai une grosse tache dans mon code, une manip' que dois faire souvent que je trouves débile :
    A chaque fois que je tentes une action de CRUD avec un objet chargé par NHibernate qui a une collection (<BAG />) d'objets enfant j'ai obligatoirement un message qui me dit que l'objet ne peut pas être utilisé par deux objets session.
    Et la seule parade que j'ai trouvé: c'est de faire des méthode qui me créé des copies de mes objets entités(soit de nouvelles instances de collections d'objets enfants avec un parcours de collection pour la remplire...), soit du code bien porcasse, pas opti pour un sou...

    Enfin, vu le code que j'ai produit pour l'instant (la moitié ne me plait pas) les astuces que je doit utiliser une fois sur deux avec des objets "hiérarchiques", je pense que je vais prendre une prestation de soutiens pour NHibernate avant qu'il n'y ait trop de code de produit.

    Encore merci pour ces réponses

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 273
    Points : 2 203
    Points
    2 203
    Par défaut
    Citation Envoyé par Philenain Voir le message
    D'abord merci pour ta réponse,

    Le coup du session.flush() c'est un reste d'un bout de code que j'avais tenté pour résoudre un soucis que j'ai eu, et que j'ai toujours d'ailleurs, avec NHibernate.

    En fait: j'ai une grosse tache dans mon code, une manip' que dois faire souvent que je trouves débile :
    A chaque fois que je tentes une action de CRUD avec un objet chargé par NHibernate qui a une collection (<BAG />) d'objets enfant j'ai obligatoirement un message qui me dit que l'objet ne peut pas être utilisé par deux objets session.
    Et la seule parade que j'ai trouvé: c'est de faire des méthode qui me créé des copies de mes objets entités(soit de nouvelles instances de collections d'objets enfants avec un parcours de collection pour la remplire...), soit du code bien porcasse, pas opti pour un sou...

    Enfin, vu le code que j'ai produit pour l'instant (la moitié ne me plait pas) les astuces que je doit utiliser une fois sur deux avec des objets "hiérarchiques", je pense que je vais prendre une prestation de soutiens pour NHibernate avant qu'il n'y ait trop de code de produit.

    Encore merci pour ces réponses
    Effectivement, derrière l'apparente facilité de la génération de code et des tutos, les ORM sont tous complexes avec un lot important de notions et de comportements à appréhender.

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/08/2011, 16h06
  2. [Code Review] Suppression des objets?
    Par LittleWhite dans le forum Qt
    Réponses: 8
    Dernier message: 29/08/2009, 18h15
  3. Suppression des objets touchant le bord
    Par Natrio dans le forum OpenCV
    Réponses: 0
    Dernier message: 23/02/2009, 14h28
  4. Suppression des enregistrements enfants
    Par tommy_f dans le forum Forms
    Réponses: 7
    Dernier message: 12/09/2007, 09h43
  5. Réponses: 3
    Dernier message: 15/12/2006, 18h52

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