NonUniqueObjectException,即使对象相同

本文关键字:对象 NonUniqueObjectException | 更新日期: 2023-09-27 18:19:23

我只是不能得到它抛出NonUniqueObjectException的原因。NHibernate文档清楚地说明:

saveOrUpdate() does the following:
if the object is already persistent in this session, do nothing
if another object associated with the session has the same identifier, throw an exception
....
因此,只有当与会话关联的另一个对象具有相同的标识符时,它才应该抛出异常。我的对象有他们的Equals和GetHashCode被覆盖(_idCopy用于另一种场景,对于我的情况总是为空):
    public override bool Equals(object obj)
    {
        return Equals(obj as SimplePersistantEqualSupported);
    }
    public override int GetHashCode()
    {
        if (_idCopy != null)
        {
            return _idCopy.GetHashCode();
        }
        return Id.GetHashCode();
    }
    public virtual bool Equals(SimplePersistantEqualSupported other)
    {
        if (other == null)
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }
        if (_idCopy != null)
        {
            // User _idCopy instead of id.
            if (!IsTransientIdCopy(this) && !IsTransientIdCopy(other) && Equals(_idCopy, other._idCopy))
            {
                return GetType().IsAssignableFrom(other.GetType()) ||
                       other.GetType().IsAssignableFrom(GetType());
            }
            return false;
        }
        if (!IsTransient(this) && !IsTransient(other) && Equals(Id, other.Id))
        {
            return GetType().IsAssignableFrom(other.GetType()) ||
                   other.GetType().IsAssignableFrom(GetType());
        }
        return false;
    }
    private static bool IsTransient(SimplePersistantEqualSupported obj)
    {
        return obj != null && Equals(obj.Id, default(int));
    }
    private static bool IsTransientIdCopy(SimplePersistantEqualSupported obj)
    {
        return obj != null && Equals(obj._idCopy, default(int));
    }

我知道我在会话中有相同标识符的对象。我与分离的对象一起工作,这就是它的目的。但由于它们是相等的——它们不是另一个对象,它们是相同的。当我查看NHibernate的源代码时,我没有看到对象的.Equals()检查——只要会话中存在具有相同标识符的任何内容,它就会抛出异常:

public void CheckUniqueness(EntityKey key, object obj)
    {
        object entity = GetEntity(key);
        if (entity == obj)
        {
            throw new AssertionFailure("object already associated, but no entry was found");
        }
        if (entity != null)
        {
            throw new NonUniqueObjectException(key.Identifier, key.EntityName);
        }
    }

当我在此时调试时,我可以确保obj.Equals(GetEntity(key)) == trueGetEntity(key).Equals(obj) == true。我做错了什么?

我不想在应用程序中使用.Merge,因为任何对象都可以在会话中拥有它的克隆,所以这意味着我必须将每个SaveOrUpdate更改为Merge。

乌利希期刊指南。我试图SaveOrUpdate的对象有另一个对象作为双向多对多。所以NHibernate走过对象树,去my object -> another object that many-to-many -> my object,并在那失败,即使第一个my object和第二个my object是相等的引用!

NonUniqueObjectException,即使对象相同

NHibernate不需要做一个相等的检查。它已经知道给定的实体不在会话中,因为StatefulPersistenceContext.GetEntry()返回null。它确实返回null,因为它通过引用相等性搜索条目。因此,如果会话中的任何其他对象具有与给定对象相同的Id,则必须抛出异常以遵循文档。

两个相等的对象不必相同。"相同"通常用来表示两个引用指向同一个对象(引用相等)。

PS:与你的问题无关,但似乎你的Equals实现对于比较使用继承映射的实体的代理是不安全的(代理只继承基类,所以它不能分配给继承的类)。