OK, peu importe la façon dont je définis ces mappages, ma cartographie plusieurs à plusieurs personnes ne veut pas fonctionner avec une insertion en cascade. J'ai essayé diverses combinaisons de C'est vraiment simple: j'ai un message Voici donc la conception de la table (avoir supprimé la relation de p> et voici les mappages: p> et j'appelle cela et cela ne fonctionne pas (tableau cascade () code> avec
inverse () code> et en supprimant toutes les propriétés inutiles pour comprendre s'ils avaient quelque chose à voir avec cela ne fonctionnant pas, mais pas de verrouillage.
code> (comme un email) envoyé à partir d'un utilisateur (j'ai appelé l'entité
basicuser code>) à un certain nombre de Utilisateurs (via la propriété
à code>).
Utilisateur CODE> et
Message Code> en termes de destinataires a une relation de plusieurs à plusieurs mais
fromUser code> a un à plusieurs. FromUser fonctionne bien et il est mis à jour d'accord mais mon problème est avec plusieurs à plusieurs. J'ai même supprimé
deuser code> et relation juste pour vérifier si c'était le problème, mais n'a pas aidé. P>
de code> à
basicuser code> pour la simplicité) p>
basiqueReMersage code> ne va pas peupler):
(Notez que les utilisateurs avec ID 1, 2 et 3 existent - j'ai également essayé de les obtenir de la base de données, puis d'ajouter à la liste ne fonctionnant toujours pas) P>
ISessionFactory factory = GetSessionFactory();
ISession session = factory.OpenSession();
Message m = new Message()
{
Body = "Please note 2",
Subject = "Secret 2",
From = new BasicUser(){Id = 2},
SentAt = DateTime.Now,
};
m.To.Add(new BasicUser(){Id = 1});
m.To.Add(new BasicUser(){Id=3});
session.SaveOrUpdate(m);
session.Close();
4 Réponses :
Vous avez fait des deux références inverse. Cela signifie à NH: ne le stockez pas de ce côté, car il est déjà stocké par l'autre côté. Si les deux sont inverse, rien n'est stocké. P>
supprimer inverse de l'une des références. p>
J'ai testé toutes sortes d'allllllllllllllll. J'ai testé avec un Invers () Code> Mais vous avez raison, pour la question, il doit être propre et je l'ai supprimé.
Il semble que j'avais oublié de supprimer le inverse () code>. J'ai enlevé le supplément.
Et les deux références sont-elles cohérentes en mémoire? NH stocke ce que vous avez en mémoire, et s'il est incompatible, vous obtenez des résultats étranges.
Vous devez envelopper votre code en transaction. Sinon, NHibernate ne économisera pas de valeurs dans la table de jonction p>
Votre réponse est fausse. Cela n'a rien à voir avec les transactions ... veuillez le supprimer.
Avez-vous essayé ce qu'il a suggéré? L'absence d'une transaction est souvent la cause de ce type de problèmes. En outre, une réponse incorrecte n'a pas besoin d'être supprimée (et peut être utile pour d'autres personnes qui rencontrent cette question à une date ultérieure).
J'ai répondu à cela non seulement pour répondre. J'ai eu un problème et une transaction similaires a aidé ...
@James, existe-t-il un exemple de travail de relation de plusieurs à plusieurs, qui met à jour la table commune? Si oui, pouvez-vous me signaler?
@Sly, merci. Eh bien, vous avez raison - dans un scénario monde réel, je l'ai utilisé une transaction. Mais le fait que NHibernate nécessiterait une opération de travail me confond vraiment. :( Pour être franc, je suis vraiment déçu par obtenir NH.
:) Eh bien, je souhaite. Si seulement cela aurait résolu mon problème. Je suis surpris, tout le monde pourrait me signaler à un exemple de travail?
Sly a raison. Cela a fonctionné pour moi lorsque je l'ai enveloppé dans une transaction. Assurez-vous de commettre votre transaction à la fin de la portée. Considérez cet exemple, tables chantillant code> et
personne code>. Les nombreux tableaux ont été appelés
chansitePerson CODE> et contenaient deux colonnes:
chanson d'emploi code> et
PersonID code>. Contrairement à votre exemple, j'ai utilisé la cascade des deux côtés, je ne sais pas si cela compte. Semblable à votre exemple, j'avais inverse d'un côté et spécifié le nom de la table. Contrairement à votre exemple, je n'ai pas spécifié le parentkeyColumn / ChildkeyColumn, les paramètres par défaut ont fonctionné. Ne soyez pas découragé, NHibernate est excellent si elle est protégée correctement.
Pas complètement vrai: session.flush () est absolument suffisant pour gérer les enregistrements d'enfants qui vont avec l'entité principale. Depuis que itransaction.commit fait la même chose sous le capot, il est correct d'utiliser (et la sécurité des transactions est, BTW, un bon addenda de toute façon)
Vous devez rendre les objets de baseAuser persistants:
ISessionFactory factory = GetSessionFactory(); ISession session = factory.OpenSession(); Message m = new Message() { Body = "Please note 2", Subject = "Secret 2", From = new BasicUser(){Id = 2}, SentAt = DateTime.Now, }; var basicUser1 = new BasicUser(){Id = 1}; session.Save(basicUser1); m.To.Add(basicUser1); var basicUser3 = new BasicUser(){Id = 3}; session.Save(basicUser3); m.To.Add(basicUser3); session.Save(m); session.Flush();
Salut Jamie, comme je l'ai mentionné, la base de données contient des identifiants de base de 1, 2 et 3. Ils sont déjà dans la base de données. B>
C'est un harnais simplifié, pas un référentiel. Bien entendu, dans le motif de référentiel, j'aurais une iunitofwork qui serait créée dans un en utilisant la déclaration code>.
Votre code crée de nouveaux basiques, ne les récupérant pas de la base de données. Si vous avez essayé de les obtenir de la base de données, ce sont vos paramètres inverse, comme dit Stefan.
Je l'ai fait de cette façon aussi. Il suffit de lire attentivement la question, n'est-ce pas?
La réponse à propos des transactions est correcte-accidentelle-occurrence. L'occurrence correcte est également correcte, c'est que cela se manifeste comme tel, car vous utilisez quelque chose comme un générateur code> identité code> qui nécessite un voyage de base de données sur Enregistrer pour obtenir l'identité. P>
Voici ce que NHibernate fait lorsque vous définissez un Enregistrez l'entité mère. Cela va immédiatement à la base de données à cause de la stratégie d'identité. La collection est "modifiée" (car c'est nouveau), alors regardons ses membres. Cette étape ne se produit que si mais attendez, certaines de ces entrées sont transitoires. Les cascades sont correctement définies, c'est bon - mais afin de créer l'entrée de la table de liens dans la session, nous avons besoin de l'identifiant de ces enfants, alors sauveons-les immédiatement. P>
Maintenant, toutes les entités pertinentes sont persistantes et la session a un inséré en attente em> pour toutes les entrées de la table de liaison. Flushing La session émettra les commandes et créera ces entrées. P>
Lorsque vous enveloppez votre code dans une transaction, commettez la transaction affleurant la session, de sorte que cela est créé lorsque vous vous engagez. Si vous utilisez un générateur d'identité qui ne nécessite pas de rond-aller-retour de DB, les entrées de la table de liaison et les entités sont toutes insérées en même temps, de sorte que vous ne verrez pas la "déconnexion" que vous voyez - si La session n'est jamais rinçue, rien n'est jamais inséré, et quand il est rincé, tout est inséré. Si vous n'avez aucune de ces choses, rincer votre session explicitement créera les entrées de la table de liaison et tout ira bien. P> Save-update code> cascade (ou une cascade qui implique que) sur une association nombreuses à plusieurs: p>
inverse code> n'est pas défini sur la cartographie du parent de la relation. Créez une entrée dans la table de liens pour chacun d'eux. P>