2013-04-09 71 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