实体框架中的 ICollection < T > Vs List < T >

在我开始设计一些实体框架应用程序之前,我只看了几次网络广播。我真的没有读过那么多的文件,我觉得我现在正在为此受苦。

我一直在课堂上使用 List<T>,效果很好。

现在我已经阅读了一些文档,其中说明我应该使用 ICollection<T>。我改成了这样,它甚至没有引起模型上下文的变化。这是因为 List<T>ICollection<T>都继承 IEnumerable<T>,而这是 EF 实际上所需要的吗?

然而,如果是这种情况,为什么 EF 文档没有说明它需要 IEnumerable<T>而不是 ICollection<T>

无论如何,我的所作所为有什么缺点吗? 或者我应该改变它吗?

95669 次浏览

实体框架将使用 ICollection<T>,因为它需要支持不属于 IEnumerable<T>接口的 Add操作。

还要注意,您使用 ICollection<T>曾经是,只是将其作为 List<T>实现公开。List<T>带来了 IList<T>ICollection<T>IEnumerable<T>

至于您的变化,通过界面暴露是一个很好的选择,尽管 List<T>工作。接口定义契约,但不定义实现。实现 可以的更改。例如,在某些情况下,实现可能是 HashSet<T>。(顺便说一下,这种思维模式不仅仅适用于实体框架。一个好的面向对象实践是面向接口而不是面向实现编程。实现可以而且将会改变。)

他们之所以选择这个接口,是因为它提供了一个可理解的抽象,而不是使用 Linq 时实体框架执行的神奇查询。

下面是接口之间的区别:

  • IEnumerable<T>是只读的
  • 可以向 ICollection<T>添加和删除项
  • 您可以对 List<T>进行随机访问(通过索引)

除此之外,ICollectionIEnumerable可以很好地映射到数据库操作,因为查询和添加/删除实体是在数据库中可能要做的事情。

通过索引进行的随机访问不能很好地映射,因为必须有一个现有的查询结果才能进行迭代,否则每次随机访问都会再次查询数据库。另外,索引会映射到什么?第几排?您希望执行的行号查询并不多,而且它对于构建更大的查询毫无用处。所以他们就是不支持。

支持 ICollection<T>,并且允许查询和更改数据,因此使用它。

List<T>之所以能够起作用,是因为 EF 实现最终会返回一个。但那是在您的查询链的末尾,而不是在开始。因此,使用属性 ICollection<T>将使 EF 创建大量 SQL 并且只在结尾返回 List<T>变得更加明显,而不是对您使用的每个级别的 Linq 执行查询。

ICollection 与 IEnumable 的不同之处在于,您实际上可以向集合中添加项,而使用 IEnumable 则不能。例如,在您的 POCO 类中,如果希望将集合添加到。让 ICollection 虚拟化,也可以从延迟加载中获益。

尽管这个问题几年前就已经发布了,但是当有人在寻找同样的场景时,这个问题仍然有效。

最近有一篇[2015] CodeProject 文章,它在很多细节和图形表示方面解释了与 示例代码的区别。它没有直接针对 EF,但仍希望它能提供更大的帮助:

List vs IEnumable vs IQueryable vs ICollection vs IDictionary