NHibernate - KeyNotFoundException: 在字典中未找到给定的键

11

更新:我已经解决了这个问题

我有下面这段代码,应该最终更新一条记录

if (session.Contains(entity))
{
    session.Evict(entity);
}

当使用Session.Evict(entity)时会出现KeyNotFoundException错误,错误信息如下:

给定的键在字典中不存在。

我是否理解有误?如果session.Contains(entity)为true,则应存在该键,因此session.Evict()应按预期工作吗?

堆栈跟踪如下:

System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary.

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 Core.Repository.NHibernate.Repository.NoIdRepository`1.Update(T entity) in NoIdRepository.cs: line 26
at Core.Tests.Repository.NHibernate.Repository.TestInstanceVersionRepository.Test_Saving_Data() in TestInstanceVersionRepository.cs: line 63 

2
请为其取一个更有意义的标题。 - Stefan Steinegger
你有一个复合标识吗?你实现了Equals方法吗? - Stefan Steinegger
嗨,Stefan,我有一个由3个外键组成的复合ID,并且我已经实现了Equals()和GetHashCode()方法。 - Michael S
3个回答

6
原来Equals()方法比较不正确,它检查了对象上一个额外的属性的相等性,而这个属性并不是复合键的一部分。
即:
return obj != null
                   && obj is InstanceVersion
                   && this.Instance.Id == ((InstanceVersion)obj).Instance.Id
                   && this.Version == ((InstanceVersion)obj).Version
                   && this.DefaultEntry == ((InstanceVersion)obj).DefaultEntry;

DefaultEntry是一个属性。


我已经重写了equals()和gethashcode(),但错误仍然出现。 - Juran

5
这可能是NH如何识别实体的问题。它可能会使用不同的方法在Contains中查找实体,就像在Evict中一样。
如果使用复合ID,则使用实体本身作为键类型的实例,除非您实现了表示复合ID的另一个类。 EqualsGetHashCode还很重要,可以比较复合键。它需要比较键的属性。
要找出实际原因,您可以调试NH代码,或者至少查看堆栈跟踪(将其粘贴到您的问题中)。

3
我发现了答案,Equals() 方法比较有误,它检查了对象上一个额外的属性的相等性,而这个属性并不是组合键的一部分。我将更新我的答案,但我声望还不够高,所以我必须再等待5个小时 :-( - 不管怎样,感谢你们的帮助! - Michael S

0
据我理解和猜测,如果您的实体的PK是0,则您的实体不需要被驱逐,因为它尚未与数据存储关联。
如果是这样,您可以在session.Contains中检查ID != 0。

嗨,我正在更新一条记录,所以ID应该已经存在。 - Michael S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接