我遇到了你的問題,尋找同一個問題的解決方案。下面是我想出來,看它是否符合您的需求的解決方案:
首先,我所有的波蘇斯從這個抽象類派生:
public abstract class BasePOCO <T> : IEquatable<T> where T : class
{
private readonly Guid _guid = Guid.NewGuid();
#region IEquatable<T> Members
public abstract bool Equals(T other);
#endregion
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof (T))
{
return false;
}
return Equals((T)obj);
}
public override int GetHashCode()
{
return _guid.GetHashCode();
}
}
我創造,我是一個只讀GUID字段在GetHashCode()覆蓋中使用。這將確保我將派生的POCO放入字典或其他使用散列的其他內容中,如果我在過渡期間調用了.SaveChanges(),並且ID字段已由基類更新,我不會孤兒它是我不確定的完全正確的一部分,還是比Base.GetHashCode()更好?。我抽象了Equals(T other)方法,以確保實現類必須以一種有意義的方式實現它,最有可能是使用ID字段。我把Equals(object obj)覆蓋到了這個基類中,因爲它對於所有的派生類也可能是相同的。
這將是抽象類的實現:
public class Species : BasePOCO<Species>
{
public int ID { get; set; }
public string LegacyCode { get; set; }
public string Name { get; set; }
public override bool Equals(Species other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return ID != 0 &&
ID == other.ID &&
LegacyCode == other.LegacyCode &&
Name == other.Name;
}
}
ID屬性設置爲數據庫中的主鍵和EF知道。在新創建的對象上ID爲0,然後在.SaveChanges()上設置爲唯一的正整數。所以在重寫的Equals(Species other)方法中,null對象顯然不相等,顯然是相同的引用,那麼我們只需要檢查ID == 0。如果是,我們會說兩個相同類型的對象兩個ID都是0不等於。否則,如果它們的屬性都相同,我們會說它們是平等的。
我認爲這涵蓋了所有相關的情況,但如果我不正確,請給我打電話。希望這可以幫助。
===編輯1
我在想我的GetHashCode()方法是不正確的,我看着這個https://stackoverflow.com/a/371348/213169回答有關問題。上面的實現會違反約束條件,即返回Equals()== true的對象必須具有相同的哈希碼。
這是我第二次刺吧:
public abstract class BasePOCO <T> : IEquatable<T> where T : class
{
#region IEquatable<T> Members
public abstract bool Equals(T other);
#endregion
public abstract override bool Equals(object obj);
public abstract override int GetHashCode();
}
和實現:
public class Species : BasePOCO<Species>
{
public int ID { get; set; }
public string LegacyCode { get; set; }
public string Name { get; set; }
public override bool Equals(Species other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return ID != 0 &&
ID == other.ID &&
LegacyCode == other.LegacyCode &&
Name == other.Name;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return Equals(obj as Species);
}
public override int GetHashCode()
{
unchecked
{
return ((LegacyCode != null ? LegacyCode.GetHashCode() : 0) * 397)^
(Name != null ? Name.GetHashCode() : 0);
}
}
public static bool operator ==(Species left, Species right)
{
return Equals(left, right);
}
public static bool operator !=(Species left, Species right)
{
return !Equals(left, right);
}
}
所以我在基類中擺脫GUID的和移動的GetHashCode的實現。因爲ID可能會改變(不想孤兒),所以我使用Resharper的GetHashCode實現,除ID以外的所有屬性。這將滿足上面相關答案中對平等的限制。
爲什麼你的對象的ID爲0?爲什麼不像JomTois在他的代碼示例中所示,直接將一個Guid分配給ID字段/屬性。這是您提到自己的IEquatable的理想基礎。 TomTom還指出了爲每個客戶端分配一個id Range的方法,或者使用-1,-2和-3作爲臨時id,這些「解決方案」看起來並不複雜。施工後,您會生成一個新的Guid並開始營業。或者我錯過了什麼? – 2012-11-17 19:35:43
@YoupTube:整數不能毫無價值。另外,整數是32位,而GUID是128位。這意味着SQL Server可以使用Integer(在執行連接時性能的關鍵)將4倍的內存ID放在內存中。 – 2012-11-19 18:07:53
啊,我明白了。但是,您是否有大量的數據,流量,連接並需要超高性能?這總是一種折衷......我知道。但使用guid應該不是什麼大問題。然後,您可以忘記由於使用整數而導致的所有複雜問題。 – 2012-11-20 11:26:01