NHibernate throws and excludes when I try to delete an object that has many, one composite keys. Saving an object is working correctly. Here is the exception:
[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
This is what my domain looks like:
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(); } }
Here's what my mapping files look like:
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); } }
source share