Мы используем NH 2, и этот пример у нас не работает.(Не удалось распаковать тип и левый тип прокси, см. Ниже).В нем говорится, что 2 сущности с одинаковым идентификатором не равны, когда один из них является прокси (для организации), а другой - нет (для организации).Когда у нас была иерархия:
class Organization
class AOrganization : Organization
class COrganization : Organization
{
public virtual COrganization GetConcrete()
{
return null;
}
}
class DOrganization : COrganization
{
public virtual COrganization GetConcrete()
{
return this;
}
}
AOrganization aOrganization;
COrganization cOrganization;
contract = new CContract(aOrganization, cOrganization as COrganization); //(COrganization)(cOrganization.GetConcrete()),
Итак, у CContract есть поле типа COrganization.С помощью установщика
public class Contract: Entity <short>
{
public virtual COrganization COrganization
{
get { return cOrganization; }
protected internal set
{
if (cOrganization != null && value != cOrganization) // != calls ==, which calls Equals, which calls GetUnproxiedType()
throw new Exception("Changing organization is not allowed.");
}
cOrganization = value;
}
}
private COrganization cOrganization;
}
Мы создали новый Контракт, его конструктор установил поле COrganization, указывая на какую-то организацию.Затем мы вызвали UnitOfWork.Commit, NH попытался снова установить поле COrganization (с тем же идентификатором), GetUnproxiedType работал неправильно, новые и старые значения были распознаны как не равные, и было выдано исключение ...
Здесьэто место, где появилась ошибка:
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
В отладчике: otherType == COrganizationProxy - Сбой GetUnproxiedType ... thisType == DOrganization
COrganizationProxy и DOrganizationунаследовать организацию.Так что они не являются IsAssignableFrom друг для друга ...
Почему этот пример работает для вас?
Может быть, потому что у нас есть NH 2.0 или 2.1?
Или из-за простого "Организация как организация" вместо "(Организация) (cOrganization.GetConcrete ())" ?
Или потому что у нас есть реализация ==,! = ИРавны не только в организации, но и в организации?
public abstract class Organization : Entity<int>
{
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator ==(Organization object1, Organization object2)
{
return AreEqual(object1, object2);
}
public static bool operator !=(Organization object1, Organization object2)
{
return AreNotEqual(object1, object2);
}
}
public abstract class Entity<TId>
{
public virtual TId Id { get; /*protected*/ set; }
public override bool Equals(object obj)
{
return Equals(obj as Entity<TId>);
}
private static bool IsTransient(Entity<TId> obj)
{
return obj != null &&
Equals(obj.Id, default(TId));
}
private Type GetUnproxiedType()
{
return GetType();
}
public virtual bool Equals(Entity<TId> other)
{
if (other == null)
return false;
if (ReferenceEquals(this, other))
return true;
if (!IsTransient(this) &&
!IsTransient(other) &&
Equals(Id, other.Id))
{
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
}
return false;
}
public override int GetHashCode()
{
if (Equals(Id, default(TId)))
return base.GetHashCode();
return Id.GetHashCode();
}
/// This method added by me
/// For == overloading
protected static bool AreEqual<TEntity>(TEntity entity1, TEntity entity2)
{
if ((object)entity1 == null)
{
return ((object)entity2 == null);
}
else
{
return entity1.Equals(entity2);
}
}
/// This method added by me
/// For != overloading
protected static bool AreNotEqual<TEntity>(TEntity entity1, TEntity entity2)
{
return !AreEqual(entity1, entity2);
}
}