EF核心一对多关系:ICollection或哈希集?

Dei*_*kis 7 .net entity-framework entity-framework-core asp.net-core

我正在阅读乔恩·史密斯(Jon P Smith)的“ Entity Framework Core in Action”。那里说:

在此处输入图片说明

当Hashet是适当的集合类型时,您能否提供一些示例?又为什么呢?

Jon*_*ith 12

我个人使用ICollection<T>普通属性,只是因为它是一个众所周知的接口,具有最小的开销,即创建an ICollection比a 快得多IList。您当然可以使用HashSet<T>,这是EF Core所使用的,但是我发现它的HashSet设置要比EF Core 难ICollection<T>一些List<T>

注意:我没有考虑任何一种的创建速度-之所以这样做是因为“框架设计准则”一书将这作为最佳实践,请参见第250页。

HashSet<T>如果使用未初始化的后备字段集合,则必须使用一个地方-请参见下面的代码:

private HashSet<Review> _reviews;
public IEnumerable<Review> Reviews => _reviews?.ToList();
Run Code Online (Sandbox Code Playgroud)

更新:使用EF Core 3,HashSet<T>已消除了必须用于未初始化的集合的限制(请参阅此问题)。您可以使用ICollection<T>List<T>等等。

IEnumerable<T>这是一种特殊情况,因为由于IEnumerable没有Addor Remove方法,它会将集合转换为只读版本。支持字段加号IEnumerable<T>(请参见上面的代码)使您可以“锁定”集合关系,以便只能在类内部进行更改(请参阅我的文章EF Core中的域驱动设计)。

使用备用字段集合时,我没有对其进行初始化,因此它们必须为HashSet<T>。这使我能够检测到我在加载实体时忘记使用.include的情况,例如,如果我加载了没有本书的书.Include(p => p.Reviews),然后访问了Reviews属性,那么我将得到一个null引用异常。这只是一种安全的编程方式。

如果您初始化一个后备字段集合,那么它可以是ICollection等,但是我不建议您初始化一个后备字段集合,因为如果您忘记了Include然后将一个项目添加到集合中,这可能会引起问题。在这种情况下,EF Core会删除所有现有评论,并将其替换为您添加的新评论。从EF Core的角度来看,它按您所说的去做,但很可能不是您想要的。