144

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

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

现在我已经阅读了一些文档,它指出我应该一直使用ICollection<T>. 我改成了这个,它甚至没有引起模型上下文的改变。这是因为 bothList<T>ICollection<T>inherit IEnumerable<T>,而这正是 EF 实际需要的吗?

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

无论如何,我所做的是否有任何缺点,或者我应该改变它吗?

4

4 回答 4

147

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

另请注意,您正在使用ICollection<T>,您只是将其公开为List<T>实现。List<T>随之而来的是IList<T>,ICollection<T>IEnumerable<T>.

至于您的更改,尽管List<T>工作,但通过界面公开是一个不错的选择。接口定义了合约,但没有定义实现。实施可能会改变。在某些情况下,例如,可能实现可能是 a HashSet<T>。(顺便说一下,这种思维方式不仅可以用于实体框架。一个好的面向对象实践是针对接口而不是实现进行编程。实现可以并且将会改变。)

于 2011-10-05T01:59:37.200 回答
72

他们选择了他们所做的接口,因为它对使用 Linq 时 Entity Framework 执行的魔术查询提供了可理解的抽象。

以下是接口之间的区别:

  • IEnumerable<T>是只读的
  • 您可以添加和删除项目到ICollection<T>
  • 您可以随机访问(按索引)List<T>

其中,ICollectionIEnumerable很好地映射到数据库操作,因为查询和添加/删除实体是您可能在数据库中执行的操作。

按索引的随机访问也不会映射,因为您必须有一个现有的查询结果才能迭代,否则每次随机访问都会再次查询数据库。另外,索引映射到什么?行号?您想做的行号查询并不多,而且在构建更大的查询时根本没有用。所以他们根本不支持它。

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

开始工作的原因List<T>是因为 EF 实现最终返回一个。但那是在查询链的末尾,而不是开头。因此,使您的属性ICollection<T>更加明显,EF 创建了一堆 SQL,并且只List<T>在最后返回 a,而不是对您使用的每一级 Linq 进行查询。

于 2011-10-05T02:00:21.483 回答
10

ICollection 与 IEnumerable 的不同之处在于您实际上可以将项目添加到集合中,而使用 IEnumerable 则不能。因此,例如,在您的 POCO 类中,如果您打算允许添加集合,则希望使用 ICollection。使 ICollection 虚拟化也可以从延迟加载中受益。

于 2011-10-05T02:01:13.563 回答
7

尽管该问题已在几年前发布,但当有人正在寻找相同的场景时,它仍然有效。

最近有一篇 [2015] CodeProject 文章用示例代码解释了许多细节和图形表示的差异。它不直接针对 EF,但仍然希望它能提供更大的帮助:

List vs IEnumerable vs IQueryable vs ICollection vs IDictionary

于 2015-05-23T18:16:27.050 回答