2009-10-02 8 views
1

S'il vous plaît pardonnez-moi si je ne l'explique pas très bien. Tout d'abord, j'utilise NHibernate 2.0 avec .NET 3.5. Fondamentalement, j'ai une entité "EntityA" (pour la simplicité) avec un ou plusieurs enfants de type EntityB. Chaque entitéB a un numéro indiquant comment elle a été créée récemment. Je voudrais supprimer tout sauf le x EntityB le plus récent. Cela fait partie d'une opération de purge.Comment supprimer efficacement tous les x enfants de l'entité parent sauf les derniers en utilisant NHibernate?

J'ai du mal à voir une manière efficace de faire ceci, Le problème est que les instances d'EntityB sont réellement assez complexes et pourraient avoir des centaines d'objets enfants eux-mêmes. La liste d'EntityB sur EntityA est paresseusement chargée et j'aimerais idéalement éviter de la charger en mémoire si possible.

J'ai essayé de transmettre une requête HQL à Session.Delete. Malheureusement, HQL ne semble pas supporter l'instruction top, donc je ne peux pas faire de sous-sélection pour choisir celles qui ne doivent pas être supprimées.

Les cascades sont définies dans NHibernate et non dans la base de données. Je ne suis pas sûr mais je me demande si NHibernate chargera le graphe d'objet entier même si la suppression est faite via HQL.

Tout conseil serait apprécié.

[Modifier] Malheureusement, toute requête doit être HQL pas SQL car il doit être la base de données indépendante [/ Modifier]

Cheers,

James

Répondre

0

Vous devriez pouvoir utiliser HQL delete Child c where c in (:list)list est une copie de la liste des enfants avec seulement les éléments à enlever. list peut être obtenue via une requête HQL telle que from Child c where c.Parent = :parent - Les requêtes HQL n'obéissent apparemment pas à la stratégie de fetch du mappage (paresseux vs désireux) et ne chercheront les enfants qu'avec empressement quand on leur demandera d'aller chercher les enfants avec impatience (left join fetch c.SubChildren) - puis filtré pour n'inclure que les éléments à supprimer.

1

De mon expérience avec NHibernate je ne pense que tu vas trouver une solution propre pour ça. Mais, cela n'a pas d'importance. Sortir du cadre n'est qu'une mauvaise chose si le cadre offre une alternative viable. Utilisez une instruction SQL paramétrée, assurez-vous qu'il est clair dans le code où et pourquoi vous faites cela et ce sera une excellente solution.

EDIT:

Je suis assez certain que vous pourriez trouver une base de données requête indépendante SQL pour cela, mais quand même ... Au lieu d'essayer d'utiliser une instruction supérieure essayez d'utiliser MAX() (en supposant qu'il est tel une fonction dans HQL) pour récupérer l'identifiant de l'élément supérieur et structurer une instruction delete avec une condition que l'identifiant ne soit pas l'identifiant MAX.

0

Si rien d'autre que vous pourriez mettre en place les cascades dans la base de données et il suffit de faire

Session.CreateSQLQuery([SqlStatement]).SetParameter([ParameterStuff]).ExecuteUpdate(); 

J'essaie toujours de garder des cascades, des valeurs par défaut, etc. mis en place à la fois la base de données et NHibernate pour les cas comme celui-ci lorsque vous devez faire quelque chose directement dans la base de données.

Questions connexes