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

wil*_*wil 98 c# ienumerable list icollection ef-code-first

在我首先设计一些Entity Framework应用程序之前,我只看了几个网络广播.我真的没有阅读那么多文档,我觉得我现在正在为此而痛苦.

我一直List<T>在我的课堂上使用,而且效果很好.

现在我已经阅读了一些文档,并说它应该一直在使用ICollection<T>.我改为这个,它甚至没有导致模型上下文改变.这是因为兼并List<T>ICollection<T>继承IEnumerable<T>,这是EF实际需要的吗?

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

在任何情况下,我做了什么都有任何缺点,或者我应该改变它?

Ant*_*ram 103

实体框架将使用,ICollection<T>因为它需要支持Add操作,而操作不是IEnumerable<T>界面的一部分.

另请注意您正在使用ICollection<T>,您只是将其作为List<T>实现公开.List<T>与它一起带来IList<T>,ICollection<T>IEnumerable<T>.

至于你的改变,通过界面曝光是一个不错的选择,尽管List<T>工作.接口定义合同但不定义实现.实施可能会改变.在某些情况下,也许实施可能是HashSet<T>例如.(顺便提一下,这是一种不仅仅是实体框架可以使用的思维模式.良好的面向对象实践是针对接口而不是实现进行编程.实现可以并且将会改变.)

  • 正常的Linq操作不会添加或改变事物,它们只是过滤,分组,项目等.只有前向,只读序列才是支持这些操作所必需的.当你有一个Linq提供者,比如实体框架来处理数据持久性时,Add的能力是一个很大的好处,需要一个更强大的界面,这就是邀请`ICollection <T>`到派对(这个界面带来了它是`IEnumerable <T>`,所以"正常"的Linq操作仍然有效). (10认同)
  • 所以....只是为了让我进一步了解-List继承IList,它继承ICollection,它继承IEnumerable? (5认同)
  • 是的,这就是链条.由于继承层次结构,`List <T>`必须实现每个接口(`IList <T>`,`ICollection <T>`,`IEnumerable <T>`).完成后,`IList <T>`也会选择非通用的`IList`,`ICollection`和`IEnumerable`接口. (2认同)

Mer*_*ham 47

他们选择了他们所做的界面,因为它为您在使用Linq时实体框架执行的魔术查询提供了可理解的抽象.

这是接口之间的区别:

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

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

索引的随机访问也不会映射,因为您必须有现有的查询结果进行迭代,或者每次随机访问都会再次查询数据库.此外,索引将映射到什么?行号?您不想进行大量的行号查询,并且在构建更大的查询时根本没用.所以他们根本就不支持它.

ICollection<T> 支持,并允许您查询和更改数据,所以使用它.

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


Ral*_*lle 8

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


BiL*_*LaL 7

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

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

List vs IEnumerable vs IQueryable vs ICollection vs IDictionary