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.