1

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

我似乎在其他问题中提出了一些建议,将Hashset集合类型用于多对多关系并覆盖 Equals() 和 GetHashCode()。

为什么要使用哈希集?

我如何覆盖这些方法,这有什么作用?

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

}
4

1 回答 1

2

为什么要使用哈希集?

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

我如何覆盖这些方法,这有什么作用?

实体框架中的多对多关系没有不同的实体来表示关系,因此没有实体可以覆盖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 是不必要的。即使实体满足多对多关系,数据库也会强制组合键的唯一性。

于 2013-04-11T20:24:12.683 回答