我們使用NH 2並且此示例對我們不起作用(它未能取消對代理類型的處理並留下代理類型,見下文) 它說,2個實體使用相同的ID是不相等的,當其中一個是COrganization的代理()和其他不(DOrganization) 當我們有一個層次:。
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有一個組織類型的領域。使用一個設置器
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;
}
我們構造了新的Contract,它的構造函數設置了指向某個組織的COrganization字段。然後我們調用UnitOfWork.Commit,NH嘗試再次設置COrganization字段(使用相同的ID),GetUnproxiedType工作不正確,新舊值被認爲是不相等的,並拋出異常...
這裏是錯誤露面的地方:
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
在調試器:OTHERTYPE == COrganizationProxy - GetUnproxiedType失敗... thisType == DOrganization
COrganizationProxy和DOrganization既繼承COrganization 。 所以他們不是IsAssignableFrom彼此...
爲什麼這個例子適合你?
也許是因爲我們有NH 2.0或2.1?
因爲簡單「cOrganization爲COrganization」,而不是「(COrganization)(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);
}
}
你可以附加'GetType()'方法的實現嗎?沒有看到它,我猜測它返回「具體」的基礎類(例如 - 對於ProductProxy我想它應該返回'Product' – 2011-04-17 08:42:23
productProxy是由NHibernate創建的動態代理類,所以我不知道實現..我想也許有人洞察到如何NHibernate創建代理將能夠幫助..也GetType()不是虛擬的,所以似乎是實現它作爲「新」在代理類不會有任何影響所有.. – 2011-04-17 09:23:56
我有同樣的書,我不是所提供的Equals實現的大粉絲,它太依賴於對象的持久性了,本書指出如果任何一個實體都是瞬態的(不保存到db),那麼這個Equals總是返回false,首先我相信這打破了持久性無知規則,其次,如果我想在保存到數據庫之前檢查相等性,我實現了部分效率(ch eids),但我仍然實施一個「邏輯」等於所有我的對象。 – brainimus 2011-04-20 19:31:22