NHibernate - KeyNotFoundException: данный ключ отсутствовал в словаре

Обновление: я исправил эту проблему

У меня есть следующий блок кода, который должен в конечном итоге обновить запись

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

какие ошибки в Session.Evict(entity) с KeyNotFoundException и следующее сообщение:

Указанный ключ отсутствует в словаре.

Я что-то не понимаю? Я предполагаю, что если session.Contains(entity) истинно, тогда ключ должен существовать и, следовательно, 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 

Ответ 1

Оказывается, что метод 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 является свойством.

Ответ 2

Это может быть проблема того, как NH идентифицирует объект. Он может использовать другой метод для поиска объекта в Contains, как в Evict.

Если вы используете составной идентификатор, он использует экземпляры самого объекта как тип ключа, если только вы не внедрили другой класс, который представляет составной идентификатор. Equals и GetHashCode также важны для сравнения составного ключа. Он должен сравнить свойства ключа.

Чтобы найти фактическую причину, вы можете отлаживать NH-код или, по крайней мере, заглядывать в трассировку стека (вставьте его в свой вопрос).

Ответ 3

к моему пониманию и предположению, если PK вашего entity 0, ваша сущность не должна быть высечена, поскольку еще не связана с хранилищем данных.

Если это так, вы можете проверить ID != 0 в && с session.Contains.