为什么要使用哈希集?
你不应该。只要映射正确,多对多行的唯一性将在数据库级别强制执行。在应用程序级别强制执行它几乎没有任何好处。
我如何覆盖这些方法,这有什么作用?
实体框架中的多对多关系没有不同的实体来表示关系,因此没有实体可以覆盖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 是不必要的。即使实体满足多对多关系,数据库也会强制组合键的唯一性。