78 votes

Comment faire pour supprimer l'enfant objet dans NHibernate?

J'ai un objet parent qui a une relation avec un IList d'objets enfants. Quelle est la meilleure façon de supprimer l'enfant des objets? Je ne suis pas la suppression de la mère. Mon objet parent contient un IList d'objets enfants. Voici la cartographie de la "un à plusieurs" de la relation:

<bag name="Tiers" cascade="all">
  <key column="mismatch_id_no" />
  <one-to-many class="TGR_BL.PromoTier,TGR_BL"/>
</bag>

Si j'essaie de supprimer tous les objets de la collection en utilisant clear(), puis d'appeler SaveOrUpdate(), j'obtiens cette exception:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column

Si j'essaie de supprimer les objets enfants individuellement, puis les retirer de la société mère, j'obtiens une exception:

deleted object would be re-saved by cascade

C'est mon premier temps à traiter avec la suppression des objets enfants dans NHibernate. Ce que je fais mal?

edit: Juste pour préciser - je ne cherche PAS à supprimer l'objet parent, l'enfant des objets. J'ai la relation définie comme "un à plusieurs" sur le parent. Dois-je aussi besoin de créer une many-to-one relation de l'enfant objet de la cartographie?

136voto

Chuck Points 6314

Vous êtes l'obtention de la première erreur, car, lorsque vous retirez les objets de la collection, NHibernate du mode de fonctionnement par défaut est tout simplement de rompre l'association. Dans la base de données, NHibernate tente de définir la colonne de clé étrangère sur la ligne enfant pour les nuls. Puisque vous n'avez pas autoriser les valeurs null dans la colonne, SQL Server génère l'erreur. De compensation de la collecte ne sera pas nécessairement supprimer l'objet enfant, mais une façon de le faire est de mettre en cascade=all-delete-orphan. Cette annonce NHibernate qu'il devrait supprimer le nouveau orphelins des lignes à la place de réglage de la colonne de clé étrangère.

Vous obtenez la deuxième erreur, car lorsque vous appelez SaveOrUpdate NHibernate supprime tous les objets enfants. Ensuite, parce que ni la relation est marquée comme inverse, NHibernate tente également de définir la colonne de clé étrangère dans votre table enfant à null. Puisque les lignes ont déjà été supprimés, vous recevez le deuxième erreur. Vous devez définir inverse=true sur un côté de votre relation pour résoudre ce problème. Cela se fait habituellement sur la une (clé primaire ou d'un parent). Si vous ne le faites pas, NHibernate fera les mises à jour appropriées pour chaque côté de la relation. Malheureusement, l'exécution de deux mises à jour n'est pas la bonne chose à faire.

Vous devriez toujours marquer un côté de vos relations comme l'inverse de côté. Selon la façon dont vous code, vous pouvez ou ne pouvez pas besoin d'utiliser en cascade. Si vous souhaitez profiter d'un seul coup supprime que vous êtes en train de faire à l'aide de(), vous devez définir votre cascade.

3voto

hanuman0503 Points 138

Selon Chuck réponse, j'ai résolu mon problème en ajoutant Inverse = true dans le parent du côté de la cartographie:

Message a beaucoup de MessageSentTo:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}

Je suis à l'aide de Château ActiveRecord. Merci Chuck.

2voto

Liath Points 3759

Dans notre exemple, nous avons les catégories avec de nombreux produits où un produit n'est pas les valeurs null.

Vous pouvez contourner le problème en supprimant le produit et la retirer de la mère de la collection avant la chasse d'eau, mais nous sommes toujours à la recherche d'une meilleure solution à cette question.

product = pRepo.GetByID(newProduct.ProductID);
product.Category.Products.Remove(product);
pRepo.Delete(product);

Espérons qu'il aidera de toute façon

2voto

Elie Points 7628

Essayez d'utiliser merge() au lieu de saveOrUpdate(). Aussi, assurez-vous que votre cascade est réglé sur all-delete-orphan et que votre relation parent-enfant est inversible (l'inverse=true sur le parent et puis, un domaine que l'enfant est le parent-id avec les non-null=true).

0voto

Thomas Tekavec Points 41

Changement cascade de la valeur de l'attribut de "tout" à "all-delete-orphan".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X