为什么要使用的Hashset?
你不应该。多对多行的唯一性将在数据库级别执行,只要它正确映射即可。在应用程序级别执行它几乎没有任何好处。
我该如何重写这些方法?
实体框架中的多对多关系没有明确的实体来表示关系,因此没有实体可以覆盖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是不必要的。即使实体满足多对多关系,数据库也会强制实现组合键的唯一性。
感谢您的回复。 “你可以定义一个实体来满足多对多的关系”。这不是我用'UserChartQuery'实体表示一个连接表吗?如果是这种情况,我正在寻找一个代码示例如何重写这些方法,因为我无法找到一个。另一方面,如果你建议我在没有连接表的情况下使用不同的映射,那么请告诉我如何配置这样的映射,因为我一直在挣扎,直到我用连接表得到我想要的。 – parliament 2013-04-12 07:23:14
是的,这正是你用UserChartQuery所做的。对不起,我第一次没注意到。我已经更新了答案。如果您还有其他问题,请告诉我。 – 2013-04-12 15:17:09
谢谢你的更新,赏赐你的。作为最后一点,您能想到在应用程序级别实施唯一性的任何好处吗? – parliament 2013-04-12 22:07:27