EF Hashset集合 - 覆盖Equals和GetHashCode

时间:2013-04-09 18:31:52

标签: entity-framework

我与EF中的连接表有很多关系。

我在其他问题中似乎有一些建议,要求Hashset集合类型用于多对多关系并覆盖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 个答案:

答案 0 :(得分:1)

我为什么要使用Hashset?

你不应该。只要映射正确,就会在数据库级别强制执行多对多行的唯一性。在应用程序级别执行它几乎没有任何好处。

如何覆盖这些方法以及这取得了什么成果?

实体框架中的多对多关系没有用于表示关系的独特实体,因此没有实体可以覆盖Equals()GetHashCode()

可以定义一个实体以满足多对多关系,但从对象模型的角度来看,这有点人为和​​丑陋。如果你这样做,你将覆盖Equals()GetHashCode(),并将相等性定义为参与的密钥彼此相等,并且哈希码将是参与密钥的唯一组合。 / p>

<强>更新

将您的示例与代表多对多关系的实体一起使用,这就是您实现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是不必要的。即使实体满足多对多关系,数据库也会强制复合密钥的唯一性。