爲什麼要使用的Hashset?
你不應該。多對多行的唯一性將在數據庫級別執行,只要它正確映射即可。在應用程序級別執行它幾乎沒有任何好處。
我該如何重寫這些方法?
實體框架中的多對多關係沒有明確的實體來表示關係,因此沒有實體可以覆蓋Equals()
和GetHashCode()
。
你可能定義了一個實體來滿足多對多的關係,但這是從對象模型的角度來看有點人爲和醜陋。如果您要這樣做,則將覆蓋Equals()
和GetHashCode()
,並將相等性定義爲參與鍵彼此相等,並且散列碼將是參與鍵的唯一組合。使用
更新
你的榜樣與代表許多一對多關係的實體,這是你將如何實現Equals
和GetHashCode
,以便它可以HashSet的範圍內可以正常使用:
public class UserChartQuery
{
public int UserId { get; set; }
public int ChartQueryId { get; set; }
public virtual User User { get; set; }
public virtual ChartQuery ChartQuery { get; set; }
protected bool Equals(UserChartQuery other)
{
return UserId == other.UserId && ChartQueryId == other.ChartQueryId;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((UserChartQuery) obj);
}
public override int GetHashCode()
{
unchecked
{
return (UserId*397)^ChartQueryId;
}
}
}
如上所述,我推薦你使用更自然,內置的方式做在EF一個多一對多的關係:
public class ChartQuery
{
public int ChartQueryId { get; set; }
public virtual ICollection<User> Users { get; set; }
...more...
}
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<ChartQuery> SavedChartQueries { get; set; }
...more...
}
在你的映射,那麼您需要定義許多一對多的關係,這樣的(在的DbContext OnModelCreating覆蓋):
builder.Entity<ChartQuery>()
.HasMany(cq => ucq.Users)
.WithMany(u => u.SavedChartQueries);
在任何情況下,我真的覺得用一個HashSet是不必要的。即使實體滿足多對多關係,數據庫也會強制實現組合鍵的唯一性。
感謝您的回覆。 「你可以定義一個實體來滿足多對多的關係」。這不是我用'UserChartQuery'實體表示一個連接表嗎?如果是這種情況,我正在尋找一個代碼示例如何重寫這些方法,因爲我無法找到一個。另一方面,如果你建議我在沒有連接表的情況下使用不同的映射,那麼請告訴我如何配置這樣的映射,因爲我一直在掙扎,直到我用連接表得到我想要的。 – parliament 2013-04-12 07:23:14
是的,這正是你用UserChartQuery所做的。對不起,我第一次沒注意到。我已經更新了答案。如果您還有其他問題,請告訴我。 – 2013-04-12 15:17:09
謝謝你的更新,賞賜你的。作爲最後一點,您能想到在應用程序級別實施唯一性的任何好處嗎? – parliament 2013-04-12 22:07:27