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 は別のシナリオで使用され、私の場合は常に null です):
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)) == true
とGetEntity(key).Equals(obj) == true
. 私は何を間違っていますか?
私は.Mergeを使用したくありません。アプリケーションでは、どのオブジェクトもセッションでクローンを持つことができるため、すべてのSaveOrUpdateをMergeに変更する必要があることを意味します。
更新。私が SaveOrUpdate しようとしているオブジェクトには、双方向の多対多として別のオブジェクトがあります。そのため、NHibernate はオブジェクト ツリーをたどり、my object
-> another object that many-to-many
->に移動し、1 番目と 2 番目が参照によって等しいmy object
にもかかわらず、失敗します。my object
my object