2010-12-10 17 views
6

i ont x qui un objet de type ObjectX qui possède une propriété ListOfObjectYs thats unEn NHibernate, pas en mesure de mettre à jour la liste des objets enfant

List<objectY> 

la cartographie NHibernate ressemble à ceci:

public ObjectXMap() 
    { 
     HasMany(x => x.ListOfObjectYs).AsBag().Inverse(); 
    } 

quand je vais l'enregistrer, je modifier certaines propriétés sur ObjectX et ensuite :

Session.SaveOrUpdate(x); 

maintenant j'ai besoin de mettre à jour cette propriété qui est une liste. Je reçois une nouvelle liste d'objectYs et je veux remplacer la liste existante de objectY par une nouvelle liste. Ai-je besoin de faire ça?

foreach (ObjectY y in x.ListOfObjectYs) 
       { 
        Session.Delete(y); 
        deleted = true; 
       } 
       if (deleted) 
       { 
        _session.Flush(); 
       } 
       x.ListOfObjectYs.Clear(); 

       foreach (ObjectY y in newObjectYList) 
       { 
        x.ListOfObjectYs.Add(y); 
        Session.SaveOrUpdate(y); 
       } 
       _session.Flush(); 

mes questions sont les suivantes:

  1. Dois-je supprimer tout et rincer avant d'ajouter de nouveaux.
  2. Est-ce que je dois faire tous ces incrémentiel arrêts entre

est-il une meilleure façon de faire cette mise à jour où je dois mettre à jour un objet (propriétés), mais aussi de mettre à jour des propriétés qui sont la liste où il y a une toute nouvelle liste (ce qui signifie que les éléments doivent être supprimés et ajoutés).

Répondre

3

Les réponses à vos questions sont non et non. Si vous voulez remplacer la liste, effacez-la et ajoutez de nouveaux éléments. Si vous avez défini la cascade sur all-delete-orphelin, comme dans la réponse de James Kovacs, les modifications apportées à la collection seront conservées lorsque la session sera vidée.

Il est important de comprendre ce que Save, mise à jour et saveOrUpdate signifient dans NHibernate:

  • Enregistrer - faire un nouvel objet persistant
  • Mise à jour - faire un objet modifié détaché persistant
  • de saveOrUpdate - Enregistrer ou Mise à jour en fonction de la valeur non enregistrée de l'identifiant de l'objet

Voir aussi Manipulating Persistent Data.

En supposant que tous vos objets ont été chargés dans la même session remplaçant alors une collection peut être aussi simple que:

x.ListOfObjectYs.Clear(); 
foreach (ObjectY y in newObjectYList) 
{ 
    x.ListOfObjectYs.Add(y); 
} 
_session.Flush(); 
+0

comment pouvez-vous faire cela sans réellement enregistrer les objets Y. est votre point, que cascade.AllDeleteOrphan() prend soin de cela ?? – leora

+0

J'obtiens maintenant une erreur: Une collection avec cascade = "all-delete-orphelin" n'était plus référencée par l'instance d'entité propriétaire: ObjectY – leora

+3

Si les objets Y sont nouveaux, vous devez d'abord les enregistrer pour les rendre persistants. Le message d'erreur peut indiquer que vous réaffectez la référence de collection quelque part, voir http://www.sleberknight.com/blog/sleberkn/entry/20070329 et http://stackoverflow.com/questions/2127016/nhibernate-mapping -a-collection-with-cascadeall-delete-orphelin-était-plus-long-r. –

3

Vous avez besoin d'une cascade sur votre HasMany(). Si les objets enfants sont entièrement la propriété du parent, Cascade.AllDeleteOrphan() est un bon choix. De cette façon, les sauvegardes, les mises à jour et les suppressions sur le parent sont automatiquement répercutées en cascade sur les objets enfants, ce qui élimine le besoin de votre bloc foreach complexe. Avec cela en place, il suffit de mettre à jour votre collection et de valider votre transaction. NHibernate s'occupera du reste. MISE À JOUR: Pour modifier la liste, ajoutez et supprimez simplement des éléments de la liste comme vous le feriez normalement avec une collection .NET. Par exemple:

public void RemoveY(ObjectY someY) { 
    ListOfObjectYs.Remove(someY); 
} 

public void AddY(ObjectY someY) { 
    ListOfObjectYs.Add(someY); 
} 

public void ClearAllY() { 
    ListOfObjectYs.Clear(); 
} 

Lorsque la transaction est validée, toute modification apportée à la collection ListOfObjectYs sera persisté avec le parent ObjectX.

+0

soit clair, j'ajouter Cascade.AllDeleteOrphan() à mon fichier de mappage. C'est assez simple. Pouvez-vous fournir la syntaxe pour faire la mise à jour de la liste car je ne suis pas tout à fait ce que vous voulez dire, "je peux juste supprimer le pour chaque", à un moment je dois supprimer les entrées existantes et en ajouter de nouvelles. Je ne vois pas comment je sors de ça. – leora

+0

- J'obtiens maintenant une erreur: Une collection avec cascade = "all-delete-orphelin" n'était plus référencée par l'instance d'entité propriétaire: ObjectY – leora

+0

Affectez-vous une collection à une autre? par exemple. x1.ListOfYs = x2.ListOfYs? Vous devez copier des éléments entre des collections, sans dupliquer les références aux collections. Si ce n'est pas le cas, vous devrez fournir le code approprié. –