Hi 

I'm getting a *KeyNotFoundException *while trying to evict entity from the 
session. 

Below there is a stack trace :

   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)

   at NHibernate.Engine.StatefulPersistenceContext.RemoveEntity(EntityKey 
key)

   at NHibernate.Event.Default.DefaultEvictEventListener.OnEvict(EvictEvent 
event)

   at NHibernate.Impl.SessionImpl.FireEvict(EvictEvent evictEvent)

   at NHibernate.Impl.SessionImpl.Evict(Object obj)

   at 
NHibernate.Engine.CascadingAction.EvictCascadingAction.Cascade(IEventSource 
session, Object child, String entityName, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, 
IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, 
Object child, CollectionType collectionType, CascadeStyle style, IType 
elemType, Object anything, Boolean isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object 
child, CascadeStyle style, Object anything, CollectionType type)

   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, 
Object parent, Object anything)

   at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, 
Object parent)

   at NHibernate.Event.Default.DefaultEvictEventListener.DoEvict(Object 
obj, EntityKey key, IEntityPersister persister, IEventSource session)

   at NHibernate.Event.Default.DefaultEvictEventListener.OnEvict(EvictEvent 
event)

   at NHibernate.Impl.SessionImpl.FireEvict(EvictEvent evictEvent)

   at NHibernate.Impl.SessionImpl.Evict(Object obj)

   at 
NHibernate.Engine.CascadingAction.EvictCascadingAction.Cascade(IEventSource 
session, Object child, String entityName, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, 
IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, 
Object child, CollectionType collectionType, CascadeStyle style, IType 
elemType, Object anything, Boolean isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object 
child, CascadeStyle style, Object anything, CollectionType type)

   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object 
child, IType type, CascadeStyle style, Object anything, Boolean 
isCascadeDeleteEnabled)

   at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, 
Object parent, Object anything)

   at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, 
Object parent)

   at NHibernate.Event.Default.DefaultEvictEventListener.DoEvict(Object 
obj, EntityKey key, IEntityPersister persister, IEventSource session)

   at NHibernate.Event.Default.DefaultEvictEventListener.OnEvict(EvictEvent 
event)

   at NHibernate.Impl.SessionImpl.FireEvict(EvictEvent evictEvent)

   at NHibernate.Impl.SessionImpl.Evict(Object obj)

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

I am using FluentNHibernate 1.2 + NHibernate 3.2 with AutoMapper to 
generate mappings. My entity structure is as follow :

    public class RootEntity : Entity
    {
        public OrderbasedInvoice()
        {
            Lines = new List<LineItem>();
        }
 
        [Cascade(Type = CascadeType.All)]
        public virtual Reference Reference { get; set; }
 
        public virtual IList<LineItem> Lines { get; set; } 
    }
 
    public class Reference : Entity
    {
        [DataMember, Cascade(Type = CascadeType.All)]
        public virtual LineItem Line { get; set; }
    }
 
    public class LineItem : Entity
    {
        public virtual string Name { get; set; }
    }


The *CascadeAttribute* is used for my custom conventions to allow cascade 
access to child entities. In my solution the default cascade behavior for 
IList<Entity> is All-Delete-Orphan.

Use case :

 1) I create instance of root entity with LineItem and Reference that has the 
reference to the *same *LineItem. Speaking of Id's i have object graph :


RootEntity#1 :

 Lines : { LineItem#1 }

 Reference : { LineItem#1 }


so that you can access the LineItem#1 object from two different paths in the 
graph with the cascade scope.


Now when i call evict on the rootEntity(assume i have queried it first), for 
example using :


using(var session = _sessionFactory.OpenSession())

{

   using(var tx = session.BeginTransaction())

   {

      session.Evict(rootEntity)

   }

}


i will get the *KeyNotFoundException* described above. The issue seems to be 
inside NHibernate/Engine/StatefulPersistenceContext.cs class

that has a *RemoveEntity* method :


                /// <summary>
                /// Remove an entity from the session cache, also clear
                /// up other state associated with the entity, all except
                /// for the <tt>EntityEntry</tt>
                /// </summary>
                public object RemoveEntity(EntityKey key)
                {
                        object tempObject = entitiesByKey[key];
                        entitiesByKey.Remove(key);
                        object entity = tempObject;
                        List<EntityUniqueKey> toRemove = new 
List<EntityUniqueKey>();
                        foreach (KeyValuePair<EntityUniqueKey, object> pair in 
entitiesByUniqueKey)
                        {
                                if (pair.Value == entity) 
toRemove.Add(pair.Key);
                        }
                        foreach (EntityUniqueKey uniqueKey in toRemove)
                        {
                                entitiesByUniqueKey.Remove(uniqueKey);
                        }

                        entitySnapshotsByKey.Remove(key);
                        nullifiableEntityKeys.Remove(key);
                        BatchFetchQueue.RemoveBatchLoadableEntityKey(key);
                        BatchFetchQueue.RemoveSubselect(key);
                        parentsByChild.Clear();
                        return entity;
                }

the method above does not verify if the item (entity) is present in the 
dictionary so having the same entity in the same place would cause this 
exception.
The simpliest solution would be just to add the if statement at the beginning 
and check if the dictionary contains the key. However i wonder if it a 
NHibernate
bug that i should register or am i missing something ?

Regards,
PS


 

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/nhusers/-/_v_j9vFE7e4J.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to