我找到了许多使用HashSet ex
的教程this.Supplier = new HashSet<supplier>();
在多对多的关系中。但是som教程使用下面的代码而没有HashSet(不多或少)
public partial class Product
{
public Product()
{
this.Supplier = new HashSet<supplier>();
}
public long ProductID { get; set; }
public string ProductName { get; set; }
//navigation property to Supplier
public virtual ICollection<supplier> Supplier { get; set; }
}
public partial class Supplier
{
public Supplier()
{
this.Product = new HashSet<product>();
}
public long SupplierID { get; set; }
public string SupplierName { get; set; }
// navigation property to Product
public virtual ICollection<product> Product { get; set; }
}
当我测试上面的代码并删除
时 public xxxx()
{
this.xxxx = new HashSet<xxxx>();
}
我仍然有一个关联表和多对多的关系。
为什么我需要HashSet?
答案 0 :(得分:3)
通常在两个表模型中使用ICollection
定义多对多关系:
public virtual ICollection<supplier> Supplier { get; set; }
public virtual ICollection<product> Product { get; set; }
模型上ICollection
的存在意味着启用了延迟加载,允许EF为它们创建派生类。
关于在模型世代中使用HashSet
,ChrisV在HashSet in EF many to many中说:
HashSet实现了一个非常有效的哈希表 操作,例如在大型集合中搜索单个项目。
默认情况下HashSet
的使用主要基于效率原因以及非空值,例如Yuval Itzchakov在Entity Framework:Why the collection type of entity class need to be instanced in the default constructor?中说:
使用HashSet是因为它保证了两个值 彼此相等(通过查看它们来检查相等性 GetHashCode和Equals方法)仅在集合中出现一次。 是的,您可以将具体类型更改为任何实现的类型
ICollection<T>
。
上面的解释可以概括为“HashSet
是模型构造函数中ICollection
接口的初始化步骤,它保证了每个相关模型成员之间的相等性”。 EF本身并不关心应该在ICollection
上为表模型应用哪些实现,您可以在构造函数中使用List<T>
替换HashSet<T>
,并且多对多关系仍然不会受到影响。
在模板模型(.tt文件)中,默认情况下,您可能会看到这些行生成HashSet<T>
,因为它实现了ICollection
:
foreach (var navigationProperty in collectionNavigationProperties)
{
#>
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
}
您可以通过在重新生成模型时删除或更改HashSet<T>
初始化来进行实验,但是我认为将其删除以进行大量数据操作并不是一个好习惯。