2012-05-17 5 views
4

NHibernate бросает и исключает, когда пытаюсь удалить объект, у которого есть многозначный составной ключ. Сохранение объекта работает правильно. Вот исключение:NHibernate KeyNotFoundException при удалении

[KeyNotFoundException: The given key was not present in the dictionary.] 
System.ThrowHelper.ThrowKeyNotFoundException() +28 
System.Collections.Generic.Dictionary`2.get_Item(TKey key) +7455516 
NHibernate.Engine.StatefulPersistenceContext.RemoveEntity(EntityKey key) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\StatefulPersistenceContext.cs:434 
NHibernate.Action.EntityDeleteAction.Execute() in d:\CSharp\NH\nhibernate\src\NHibernate\Action\EntityDeleteAction.cs:87 
NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:136 
NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:126 
NHibernate.Engine.ActionQueue.ExecuteActions() in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:174 
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:241 
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs:19 
NHibernate.Impl.SessionImpl.Flush() in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:1479 

Вот что мой домен выглядит следующим образом:

public class Order : EntityBase { 
    protected Order() {} 
    public Order(Guid persistenceId) : base(persistenceId) { 
     this.Lines = new List<OrderLine>(); 
    } 
    public virtual int OrderId {get; private set;} 
    IList<OrderLine> Lines {get; private set;} 
} 

public class OrderLine : EntityBase { 
    protected OrderLine() {} 
    public OrderLine(Guid persistenceId, Order order, int lineId) : base(persistenceId) { 
     this.Order = order; 
     this.LineId = lineId; 
    } 
    public virtual Order {get; private set;} 
    public virtual LineId {get; private set;} 
} 

public abstart class EntityBase { 
    protected EntityBase() {} 
    protected EntityBase(Guid persistenceId) { 
     this.PersistenceId = persistenceId; 
    } 
    public virtual Guid Persistenceid {get; private set;} 
    public bool IsTransient {get {return Equals(this.PersistenceId, default(Guid)); }} 
    public override bool Equals(object obj) { 
     if(ReferenceEquals(null, obj)) 
      return false; 
     if(ReferenceEquals(this, obj)) 
      return true; 
     if(this.GetType() != obj.GetType()) 
      return false; 
     return this.Equals((IEntity)obj); 
    } 
    public virtual bool Equals(IEntity other) { 
     if(ReferenceEquals(null, other)) 
      return false; 
     if(ReferenceEquals(this, other)) 
      return true; 
     if(this.IsTransient || other.IsTransient) 
      return false; 
     return this.PersistenceId.Equals(other.PersistenceId); 
    } 
    public override int GetHashCode() { 
     return this.IsTransient ? base.GetHashCode() : this.PersistenceId.GetHashCode(); 
    } 
} 

Вот что мои картографические файлы выглядеть следующим образом:

public class OrderClassMap : ClassMap<Order> { 
    public OrderClassMap() { 
     this.Table("Orders"); 
     this.Id(x => x.OrderId).Generated.Identity(); 
     this.Map(x => x.PersistenceId); 
     this.HasMany(x => x.Lines).Inverse().KeyColumn("OrderId").Cascade.AllDeleteOrphan(); 
    } 
} 

public class OrderLineClassMap : ClassMap<OrderLine> { 
    public OrderLineClassMap() { 
     this.Table("OrderLines"); 
     this.CompositeId() 
      .KeyReference(x => x.Order, "OrderId") 
      .KeyProperty(x => x.LineId); 
     this.Map(x => x.PersistenceId); 
    } 
} 

ответ

4

Я понял, что в результате чего ошибка. У моих сущностей все есть свойство PersistenceId, которое является GUID, чтобы однозначно идентифицировать каждый объект. В моем базовом классе EntityBase я переопределяю метод GetHashCode и возвращаю хэш-код на основе PersistenceId. Это было неправильно для NHibernate, потому что я не предоставлял хэш-код на основе ожидаемого Id NHibernate (OrderId). Я применил новый метод GetHashCode и Equals для всех объектов, и удаление работает нормально.

Смежные вопросы