2010-01-24 4 views
15

Je rencontre des problèmes avec mes mappings courants. J'ai une entité avec une collection enfant d'entités i.e Event et EventItems par exemple.nhibernate mapping: Une collection avec cascade = "all-delete-orphelin" n'était plus référencée

Si je mets ma carte en cascade de la collection à AllDeleteOrphan je reçois l'erreur suivante lors de l'enregistrement d'une nouvelle entité à la DB: NHibernate.HibernateException: Une collection avec cascade = « all-delete-orphan » n'était plus référencé par l'instance d'entité propriétaire: Core.Event.EventItems

Si je règle la cascade sur Tout cela fonctionne-t-il correctement? Ci-dessous sont mes classes et les fichiers de cartographie:

public class EventMap : ClassMap<Event> 
{ 
    public EventMap() 
    { 
     Id(x => x.Id, "Id") 
      .UnsavedValue("00000000-0000-0000-0000-000000000000") 
      .GeneratedBy.GuidComb(); 

     Map(x => x.Name); 
     HasMany(x => x.EventItems) 
      .Inverse() 
      .KeyColumn("EventId") 
      .AsBag() 
      .Cascade.AllDeleteOrphan(); 
    } 
} 

    public class EventItemMap : SubclassMap<EventItem> 
{ 
    public EventItemMap() 
    { 
     Id(x => x.Id, "Id") 
      .UnsavedValue("00000000-0000-0000-0000-000000000000") 
      .GeneratedBy.GuidComb(); 
     References(x => x.Event, "EventId"); 
    } 
} 



public class Event : EntityBase 
{ 
    private IList<EventItem> _EventItems; 

    protected Event() 
    { 
     InitMembers(); 
    } 

    public Event(string name) 
     : this() 
    { 
     Name = name; 
    } 

    private void InitMembers() 
    { 
     _EventItems = new List<EventItem>(); 
    } 

    public virtual EventItem CreateEventItem(string name) 
    { 
     EventItem eventItem = new EventItem(this, name); 
     _EventItems.Add(eventItem); 
     return eventItem; 
    } 

    public virtual string Name { get; private set; } 
    public virtual IList<EventItem> EventItems 
    { 
     get 
     { 
      return _EventItems.ToList<EventItem>().AsReadOnly(); 
     } 
     protected set 
     { 
      _EventItems = value; 
     } 
    } 
} 

    public class EventItem : EntityBase 
{ 
    protected EventItem() 
    { 
    } 

    public EventItem(Event @event, string name):base(name) 
    { 
     Event = @event; 
    } 

    public virtual Event Event { get; private set; } 
} 

Assez perplexe ici. Tous les conseils grandement appréciés.

Chev

+0

Pourquoi utilisez-vous subclassmap? Est-ce une faute de frappe? – Paco

Répondre

19

Vous devez mapper _EventItems en utilisant une stratégie d'accès afin que NHibernate accède au membre privé au lieu de la propriété. Vous obtenez cette erreur car la référence de collection est modifiée lorsque la liste est copiée dans une nouvelle liste dans _EventItems.ToList<EventItem>(). Essayez ceci:

public class EventMap : ClassMap<Event> 
{ 
    public EventMap() 
    { 
     Id(x => x.Id, "Id") 
      .UnsavedValue("00000000-0000-0000-0000-000000000000") 
      .GeneratedBy.GuidComb(); 

     Map(x => x.Name); 
     HasMany(x => x.EventItems) 
      .Access.PascalCaseField(Prefix.Underscore) 
      .Inverse() 
      .KeyColumn("EventId") 
      .AsBag() 
      .Cascade.AllDeleteOrphan(); 
     } 
    } 
} 
+0

Jamie - Je peux vous dire combien je suis reconnaissant! Être en train de devenir fou ici. – Chev

0

Vérifiez ce SO message: NHibernate: Delete a child record from the parent collection

Les commentaires à la réponse acceptée est question similaire.

Vous pouvez essayer d'enlever AsReadOnly pour votre EventItems pour vérifier si c'est la cause.

+0

Merci pour la réponse - n'a pas résolu le problème. Voir la réponse de Jamie. Cela l'a résolu. Merci pour la réponse si. – Chev

17

Je ne pense pas que la réponse acceptée soit une approche élégante. Le problème possible ici est que Chev lit des événements à partir de la base de données, puis attribue une nouvelle liste EventItem à la propriété EventItems. NHibernate lève cette exception quand vous ignorez simplement la liste des enfants précédente et assignez une nouvelle liste d'enfants.

Ce que vous devez faire est ici,

Si vous voulez jeter l'ancien EventItems, faire à la place:

events.EventItems.Clear(); 
events.EventItems.Add(new EventItem { blah blah }); 
+0

C'est la meilleure approche pour résoudre ce problème. Merci! – elvin