2009-09-24 6 views
1

Je suis en train d'avoir une simple relation plusieurs/hiérarchie en utilisant NHibernate. Je voudrais que les orphelins soient supprimés automatiquement, mais mes tentatives actuelles pour le faire aboutissent toutes à une ObjectDeletedException. Je me demande si quelqu'un peut me dire ce que je fais de façon incorrecte.NHibernate: scénario simple orphelin de suppression ne fonctionne pas

EDIT:

J'ai précisé que je charge un Foo racine, puis retirer un enfant en dehors de la session, ce qui provoque un ou plusieurs enfants à des orphelins. L'exception se produit lorsque j'appelle par la suite SaveOrUpdate (root) dans une deuxième session. Comment puis-je rectifier la différence dans la liste des enfants entre l'objet détaché et modifié par rapport à l'objet qui persiste dans la base de données?

Exemple de code en question ressemble à quelque chose comme ceci:

Foo foo = new Foo(); 
Foo child1 = new Foo(); 
Foo child2 = new Foo(); 

foo.Children.Add(child1); 
child1.Children.Add(child2); 

// session #1 
session.SaveOrUpdate(foo); 

// so far, so good 

// outside of any session 
foo.Children.Clear(); 

// session #2 
PutFoo(foo); // results in ObjectDeletedException 

L'objet a persisté:

class Foo 
{ 
    private IList<Foo> children = new List<Foo> children; 

    public virtual int Id { get; private set; } 
    public IList<Foo> Children 
    { 
     get { return children; } 
     set { children = value; } 
    } 
} 

La mise en correspondance FluentNHibernate:

class FooMap : ClassMap<SyncDir> 
{ 
    public FooMap() 
    { 
     Id(x => x.Id); 
     base.HasMany(x => x.Children).Cascade.AllDeleteOrphan(); 
    } 
} 

La méthode utilisée pour persister un objet de type Foo:

void PutFoo(Foo foo) 
{ 
    using (var session = factory.OpenSession()) 
    using (var transaction = factory.BeginTransaction()) 
    { 
     session.SaveOrUpdate(foo); 
     transaction.Commit(); 
    } 
} 

Répondre

1

Ce que je fais toujours, est de créer une relation bidrectional.

Donc, cela signifie que les enfants ont une référence à leurs parents. Lors de la suppression d'un enfant de la collection, j'ai également défini la référence au parent sur NULL.

Dans la cartographie, alors vous devez aussi indiquer la fin « inverse » de la relation. Je n'expose jamais la collection «telle quelle» en dehors de la classe.

Ainsi, je fais surtout comme ceci:

public class Foo 
{ 
    private ISet<Bar> _bars = new HashSet<Bar>(); 

    public ReadOnlyCollection<Bar> Bars { get return new List<Bar>(_bars).AsReadOnly(); } 

    public void AddBar(Bar b) 
    { 
     b.Parent = this; 
     _bars.Add (b); 
    } 

    public void RemoveBar(Bar b) 
    { 
     b.Foo = null; 
     _bars.Remove (b); 
    } 
} 


public class Bar 
{ 
    public Foo Parent { get; set; } 
} 

Puis, dans la cartographie, je mets la fin « inverse » sur la collection. Donc, cela signifie que dans ma cartographie (je l'utilise encore des fichiers XML pour spécifier le mappage), je mets l'inverse = true attribut sur la collection Les barres de la classe Foo.

+0

i ajouté le parent et les méthodes Ajouter()/Supprimer(), mais je suis encore en train l'exception lorsque vous appelez saveOrUpdate() sur le nœud racine après avoir enlevé un enfant. Je devrais mentionner que je charge la racine, alors appelez Remove() en dehors de la session. Ce n'est que lors de la suppression d'un enfant et appel SaveOrUpdate() à partir d'une deuxième session que l'exception se produit. – anthony