2009-11-12 5 views
2

En utilisant NHibernate, je cherche un moyen de mettre à jour automatiquement les collections persistantes lorsqu'un élément persistant est supprimé. Par exemple:NHibernate: Supprimer automatiquement un élément d'une collection persistante

var post = GetNewPost(); 
var blog = GetCurrentBlog(); 
blog.Posts.Add(post); 
BlogRepository.Update(blog); 

User.Posts.Add(post); 
UserRepository.Update(user); 

---- 

// Somewhere else 
var blog = GetCurrentBlog(); 
var post = blog.Posts.Last(); 
blog.Posts.Remove(post); 

NHibSession.Flush(); // Throws an ObjectDeletedException due to 'post' 
        // still being in the User.Posts collection 

Je comprends qu'il peut y avoir des problèmes avec le modèle et/ou la cartographie dans cet exemple, mais ces questions de côté, je veux trouver un moyen d'obtenir la collection User.Posts soit automatiquement mis à jour , c'est-à-dire supprimer "post" de lui-même. (Peut-être pas le meilleur exemple au monde, mais supposons qu'il existe de nombreux blogs et de nombreux utilisateurs, sans lien les uns avec les autres, à travers les messages.)

Dans cet exemple, je n'utilise qu'un seul NHibernate session. Je suis prêt à ajuster cela, mais je suis à la recherche d'un régime, et il devrait être transparent pour le modèle. Les événements NHibernate sont également sur la table s'il peut être démontré que c'est une bonne pratique.

Je crois que LINQ to SQL peut gérer cette situation, donc je suis un peu surpris que NHibernate ne peut pas (au mieux de mes capacités de recherche). Y a-t-il des cadres supplémentaires disponibles qui peuvent?

Voici les applications pertinentes pour cet exemple:

<class name="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Posts" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="PostId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="Blog" column="BlogId" /> 

    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="User" column="UserId" /> 
</class> 

<class name="App.Core.Domain.Blog, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Blogs" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="BlogId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore"> 
     <key column="PostId" /> 
     <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
</class> 

<class name="App.Core.Domain.User, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Users" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="Id" type="Guid" column="UserId"> 
     <generator class="assigned" /> 
    </id> 
    ... 
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore"> 
     <key column="PostId" /> 
     <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
</class> 
+0

Pourriez-vous coller vos fichiers de correspondance pour Blog et Message dans la réponse? – reach4thelasers

Répondre

0

Essayez de supprimer la cascade = tout sur le sac messages. Lorsque vous videz la session, postez la collection en cascade sur le message et essayez de la mettre à jour.

Vous créez un nouveau post en utilisant Blog.Posts.Add mais en essayant de le supprimer en utilisant PostsRepository.Delete (post). Choisissez une stratégie et respectez-la.

+0

J'aime votre proposition, mais Wes a bien expliqué pourquoi ce n'est pas vraiment une solution. Il ajoute une collection User.FavoritePosts, qui est également persistante et contient également une référence à la publication à supprimer.En utilisant une seule session, je devrais être méticuleux au sujet des collections référencées et vérifier et supprimer de * tout * d'entre eux avant d'avoir essayé de vidanger la session, ou j'obtiendrai la même ObjectDeletedException. – Tyson

0

Je veux affiner la question un peu plus, disons que nous étendons la situation avec la nouvelle Model

suivant Qu'advient-il lorsque notre message est associé à une autre entité en plus d'un blog? Même si nous prenons soin de ne supprimer que le post via Blog.Posts.Remove, quelle est la stratégie générale pour gérer le nettoyage d'autres associations? Supposons que nous ne puissions pas placer tous les éléments dans une racine agrégée, si nous le pouvions, nous pourrions les nettoyer tous via le RA. Donc, fondamentalement, nous avons des associations entre les racines agrégées, quelle est la meilleure pratique pour les nettoyer? Dans cet exemple, un utilisateur peut lister ses posts favoris, mais il s'agit d'une association 1 voie d'Utilisateur à Message, il n'y a pas de retour d'association. Est-ce que nous aurions besoin d'un service de domaine, pour supprimer/supprimer une entité du domaine (non seulement la rendre transitoire mais l'obtenir GCed), cela supprimerait toutes les associations? Cela rendra NHibernate heureux quand il persistera dans les changements. Dans ce cas, nous devons supprimer un post non seulement d'un blog mais de tout utilisateur qui l'a marqué comme favori. Devrait-il vivre dans un service de domaine, service d'application? Comment pouvons-nous tirer parti de ce service si une suppression en cascade se produit, disons que nous supprimons un blog qui a des messages marqués favoris, devrions-nous puiser dans les événements NHib et détecter les messages ont été supprimés et les associations de nettoyage?

Je sais que certaines personnes suggèrent d'utiliser la cascade FK dans la base de données, mais cela ne fonctionnera que si les associations ne sont pas chargées dans une session. Si elles sont chargées, elles doivent être supprimées. Ce que je n'aime pas dans cette approche, c'est qu'elle viole l'idée d'avoir un vrai modèle en mémoire qui agit comme il le ferait même si NHib et la base de données n'étaient pas là. Pensées?

+0

Quel programme utilisez-vous pour créer ces diagrammes? – reach4thelasers

+0

http://yuml.me/ – Tyson

Questions connexes