【发布时间】:2019-07-17 08:04:27
【问题描述】:
【问题讨论】:
标签: .net entity-framework asp.net-core entity-framework-core
【问题讨论】:
标签: .net entity-framework asp.net-core entity-framework-core
更新:我刚刚更新完我的书 Entity Framework Core in Action,我做了一些性能测试,结果表明,如果您进行正常查询,HashSet<T> 会更快(即在询问)。这是因为 EF Core 做了一些称为 Identity Resolution 的操作(请阅读 this in one of my articles),这对于非 HashSet 集合来说速度较慢。因此,如果您的收藏中有很多条目,那么HashSet<T> 会更好。
我个人将ICollection<T> 用于普通属性,只是因为它是一个众所周知的接口,开销最小,即创建ICollection 比IList 稍微快一点。你当然可以使用 HashSet<T>,这是 EF Core 使用的,但我发现 HashSet 比 ICollection<T> 更难设置,List<T>。
如果您使用未初始化的支持字段集合,您必须使用HashSet<T> 的一个地方 - 请参阅下面的代码:
private HashSet<Review> _reviews;
public IEnumerable<Review> Reviews => _reviews?.ToList();
更新:在 EF Core 3 中,必须对未初始化的集合使用 HashSet<T> 的限制已被移除(请参阅 this issue)。您可以使用ICollection<T>、List<T> 等。
IEnumerable<T> 是一个特例,因为IEnumerable 没有Add 或Remove 方法,它会将集合转换为只读版本。支持字段加上IEnumerable<T>(参见上面的代码)允许您“锁定”集合关系,以便只能从类内部更改它(参见我的文章Domain-Driven Design in EF Core)。
当我使用支持字段集合时,我将它们设为未初始化,因此它们需要为 HashSet<T>。这使我可以检测到何时忘记使用 .Include 加载实体时,例如如果我加载了没有.Include(p => p.Reviews) 的书,然后访问了Reviews 属性,我会得到一个空引用异常。这只是一种安全的编程方式。
如果您初始化支持字段集合,那么它可以是ICollection 等,但我不建议初始化支持字段集合,因为如果您忘记包含然后将项目添加到集合中,它可能会导致问题。在这种情况下,EF Core 会删除任何现有的评论并将其替换为您添加的新评论。从 EF Core 的角度来看,它按照您所说的做,但很可能不是您想要的。
【讨论】:
IEnumerable<T> 呢?。
IEnumerable<T> 添加了部分
HashSet<T> 很可能会更好。我一直将 ICollection<T> 与 EF6 和现在的 EF Core 一起使用。具体但次要的问题是我可以直接从List<T> 分配给ICollection,但对于HashSet<T> 需要new HashSet<T>( ... someList)。如果您在任何地方都使用HashSet<T>,请继续这样做。