0

Après avoir changé autour de mes correspondances un peu ( see my other question about cascade-delete for reasons), je l'ai essayé d'insérer un tout nouvel objet et toutes ses sous-classes.mapping NHibernate ne sauvegarde/insérez pas les clés des sous-classes insérées

Après cette autre problème a émergé, un problème avec l'insertion des clés dans la base de données. La situation est la suivante:

J'ai un objet avec 2 niveaux de sous-classes, à la fois une collection.

permet d'appeler le parent de l'objet, celui-ci a une collection de Childs, et tous les enitity dans cette collection a sa propre collection de enitities. Lesquels sont mappés comme suit.

la cartographie des parents de son <set>

<!--Parent--> 
<set name="Collection" 
    table="Table" 
    cascade="all-delete-orphan" 
    batch-size="15" 
    inverse="true"> 
    <key column="ParentID"/> 
    <one-to-many class="CollectionObject,CollectionObject-ns"/> 
</set 

Cartographie de CollectionObject

<id name="ID" column="ID"> 
    <generator class="native"/> 
</id> 

<!-- property mappings--> 
<property name="ParentID" column="ParentID" not-null="true"/> 

<!--collection mapping--> 
<set name="Collection" 
    table="Table" 
    cascade="all-delete-orphan" 
    inverse="true" 
    batch-size="15"> 
    <key column="ChildID"/> 
    <one-to-many class="CollectionObject,CollectionObject-ns"/> 
</set> 

La cartographie de la cartographie de l'objet dans la 2ème collection est similaire tot il plus haut. Le scénario envisagé serait, je sauve Parent, cela déclencherait la sauvegarde des sous-classes/collections.

par exemple. J'ai Parent avec ID = 1, Parent est rempli avec 1 collection, et cette collection a 1 collection de ses propres.

Je sauver Parent, parent reçoit un ID de base de données (identité SQL native). Maintenant, la première collection devrait avoir sa propriété ParentID remplie avec l'ID que le parent vient de recevoir de la base de données. Et la collection de la collection devrait obtenir son ChildID rempli de l'ID que l'enfant a obtenu de la base de données de la même manière que Parent a obtenu son ID. Qu'est-ce qui se passe maintenant est (j'ai vérifié créé SQL dans NHProf) Tout est inséré, avec son propre ID, Mais les collections ne reçoivent pas leur keycolumn rempli de l'ID de leur classe parent. (Au lieu juste se 0 inséré)

Donc, ma question se résume à, qu'est-ce que j'ai oublié d'ajouter à ma correspondance qui provoque l'arriver? Est-ce que la colonne clé ne fait pas ce que je pense qu'elle devrait faire? Si j'oublie d'ajouter quelque chose ici, s'il vous plaît dites-le. Je donnerai volontiers des informations supplémentaires.

mise à jour

Je pense que le problème pourrait avoir à faire avec les Childs ne pas avoir une étiquette <many-to-one>. J'ai donc essayé d'en ajouter une à la première cartographie enfant. Je suis venu avec ce

<many-to-one name="ParentID" 
      class="Parent,Parent-ns" 
      column="ParentID" 
      not-null="true"/> 

Cependant, cette installation me donne l'erreur suivante. Exception occurred getter of Parent.ParentID

avec InnerException {"Object does not match target type."}

Malheureusement, cette erreur ne me donne pas des idées de l'endroit où se poursuivre.

Répondre

1

Je pense qu'il serait utile que vous puissiez nous montrer vos classes aussi.Avez-vous vérifié que votre classe parent a vraiment une propriété ParentID du type parent, aussi je suppose que vous avez maintenant supprimé le

<property name="ParentID" column="ParentID" not-null="true"/> 

de votre cartographie et remplacé par le nombre à un? Enfin, si vous voulez que votre enfant d'objets d'avoir des collections d'objets d'enfant, l'objet enfant aura également besoin d'un grand nombre à un

<many-to-one name="CollectionObjectParent" 
      class="CollectionObject,CollectionObject-ns" 
      column="ChildID" 
      not-null="true"/> 
+0

Hey Gareth, Je ne suis pas sûr si je vous comprends tout à fait. Parent devrait avoir une propriété nommée ParentID de son propre type? comme parent ParentID {get; – marn

+0

Au lieu d'ajouter une référence à DocumentID, vous devez référencer l'objet parent réel Document. Voir le lien pour savoir comment gérer les situations parent-enfant - j'espère que ça aide http://www.nhforge.org/doc/nh/fr/index.html#example-parentchild – Gareth

+0

J'ai lu dans la documentation près de 20x mais il me manque encore quelque chose que j'ai peur. J'ai posté une solution de contournement ci-dessous, et il doit faire pour le moment, mais toujours ouvert aux suggestions. Actuellement, je regarde les sessions http://www.summerofnhibernate.com/. dans l'espoir qu'il devienne un peu plus clair pour moi. – marn

0

Malheureusement, après avoir joué avec les correspondances et la lecture de creux moitié Internet, je n'ai pas été en mesure de résoudre cela.

Le problème réside dans le fait que je ne peux pas obtenir le scénario qui <Document> obtient sa clé de la base de données <generator class="native"/> et après insère cette clé dans les propriétés ForeignKey de ses classes sous-jacentes, à l'intérieur juste un session.Save() appel.

par exemple. pour le scénario que je voudrais session.Save(document)

- * nouveau document détecté - * obtenir une nouvelle identité

- * document comporte la sous-classe avec un foreignkey à lui!
- * insérer idenity dans la foreignkey spécifiée propriétés (devinez est là le problème)

et répéter cela avec toutes les classes sous-jacentes.

J'ai cependant trouvé une solution de contournement (code le plus moche jamais, mais il fait le travail) Je ne suis pas vraiment dans le partage de code de cette merde, mais cela pourrait aider les gens à lire ici.

Je n'ai pas encore renoncé à résoudre cela de la bonne manière, mais pour le moment cela doit faire. Stil ouvert pour un coup de pouce dans la meilleure direction.

code de la merde entrante!

public void InsertDocument(Document document) 
    { 
     using (ISession session = NHibernateHelper.OpenSession()) 
     { 
      using (ITransaction transaction = session.BeginTransaction()) 
      { 
       try 
       {           
        IDocument document2 = new Document(); 
        document2.Bodyregels = document.Bodyregels; 
        //for making the query a little neater 
        document.Bodyregels = null;       

        //lets get the elusive identity 
        session.Save(document); 
        session.Flush(); 

        //reattach subclass and enter the id explicitly 
        document.Bodyregels = document2.Bodyregels; 
        foreach (DocumentBodyregel dbr in document.Bodyregels) 
        { 
         dbr.DocumentID = document.DocumentID; 
        } 

        //save it again, now with filled FK 
        session.Save(document); 
        session.Flush(); 

        //now save the final subclass with FK's 
        foreach (DocumentBodyregel dbr in document.Bodyregels) 
        { 
         foreach (DocumentBodyregelWaarde dbrw in dbr.Waardes) 
         { 
          dbrw.RegelID = dbr.ID; 
          dbrw.DocumentID = document.DocumentID; 
         } 
        } 

        //and save the entire thing again (now with FK's) 
        session.Save(document); 
        transaction.Commit(); 
       } 
       catch (Exception e) 
       { 
        transaction.Rollback(); 
        throw e; 
       } 
      } 
     } 
    }