2013-04-09 69 views
0

我與EF中的連接表有多對多的關係。EF Hashset集合 - 覆蓋等於和GetHashCode

我在其他問題似乎有一些建議使用​​集合類型的多對多關係和重寫Equals()和GetHashCode()。

爲什麼要使用Hashset?

我該如何重寫這些方法?

public class ChartQuery 
{ 
    public int ChartQueryId { get; set; } 
    public virtual ICollection<UserChartQuery> Users { get; set; } 
    ...more... 
} 

public class User 
{ 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public virtual ICollection<UserChartQuery> SavedChartQueries { get; set; } 
    ...more... 
} 

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; } 

} 

回答

1

爲什麼要使用的Hashset?

你不應該。多對多行的唯一性將在數據庫級別執行,只要它正確映射即可。在應用程序級別執行它幾乎沒有任何好處。

我該如何重寫這些方法?

實體框架中的多對多關係沒有明確的實體來表示關係,因此沒有實體可以覆蓋Equals()GetHashCode()

可能定義了一個實體來滿足多對多的關係,但這是從對象模型的角度來看有點人爲和​​醜陋。如果您要這樣做,則將覆蓋Equals()GetHashCode(),並將相等性定義爲參與鍵彼此相等,並且散列碼將是參與鍵的唯一組合。使用

更新

你的榜樣與代表許多一對多關係的實體,這是你將如何實現EqualsGetHashCode,以便它可以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是不必要的。即使實體滿足多對多關係,數據庫也會強制實現組合鍵的唯一性。

+0

感謝您的回覆。 「你可以定義一個實體來滿足多對多的關係」。這不是我用'UserChartQuery'實體表示一個連接表嗎?如果是這種情況,我正在尋找一個代碼示例如何重寫這些方法,因爲我無法找到一個。另一方面,如果你建議我在沒有連接表的情況下使用不同的映射,那麼請告訴我如何配置這樣的映射,因爲我一直在掙扎,直到我用連接表得到我想要的。 – parliament 2013-04-12 07:23:14

+1

是的,這正是你用UserChartQuery所做的。對不起,我第一次沒注意到。我已經更新了答案。如果您還有其他問題,請告訴我。 – 2013-04-12 15:17:09

+0

謝謝你的更新,賞賜你的。作爲最後一點,您能想到在應用程序級別實施唯一性的任何好處嗎? – parliament 2013-04-12 22:07:27