在我首先设计一些Entity Framework应用程序之前,我只看了几个网络广播。我真的没有阅读那么多文档,我觉得我现在正在为它而痛苦。
我在课堂上一直使用List<T>
,而且效果很好。
现在我已经阅读了一些文档,并声明我应该使用ICollection<T>
。我改为这个,它甚至没有导致模型上下文改变。这是因为List<T>
和ICollection<T>
都继承IEnumerable<T>
,这是EF实际需要的吗?
但是,如果是这种情况,为什么EF文档没有声明它需要IEnumerable<T>
而不是ICollection<T>
?
在任何情况下,我所做的事情是否有任何缺点,或者我应该改变它?
答案 0 :(得分:93)
实体框架将使用ICollection<T>
,因为它需要支持Add
操作,这些操作不属于IEnumerable<T>
界面。
另请注意, 使用ICollection<T>
,您只是将其公开为List<T>
实现。 List<T>
带来IList<T>
,ICollection<T>
和IEnumerable<T>
。
至于您的更改,尽管List<T>
工作,但通过界面公开是一个不错的选择。接口定义合同但不定义实现。实现可以更改。在某些情况下,例如,实现可能是HashSet<T>
。 (顺便提一下,这是一种不仅仅是实体框架可以使用的思维模式。良好的面向对象实践是针对接口而不是实现进行编程。实现可以并且将会改变。)
答案 1 :(得分:46)
他们选择了他们所做的界面,因为它为使用Linq时实体框架执行的魔术查询提供了一个可理解的抽象。
这是接口之间的区别:
IEnumerable<T>
是只读的ICollection<T>
List<T>
其中,ICollection
和IEnumerable
可以很好地映射到数据库操作,因为查询和添加/删除实体是您可能在数据库中执行的操作。
索引的随机访问也不会映射,因为您必须有一个现有的查询结果来迭代,或者每次随机访问都会再次查询数据库。此外,索引将映射到什么?行号?您不想进行大量的行号查询,并且在构建更大的查询时根本没用。所以他们根本就不支持它。
支持 ICollection<T>
,并允许您查询和更改数据,因此请使用它。
List<T>
开始使用的原因是因为EF实现最终会返回一个。但这是在您的查询链的末尾,而不是在开头。因此,使您的属性ICollection<T>
更加明显,EF会创建一堆SQL,并且最后只返回List<T>
,而不是对您使用的每个级别的Linq进行查询。
答案 2 :(得分:8)
ICollection与IEnumerable的不同之处在于您实际上可以向集合添加项目,而使用IEnumerable则不能。例如,在您的POCO类中,如果您打算允许添加集合,则需要使用ICollection。使ICollection虚拟也可以从延迟加载中受益。
答案 3 :(得分:3)
虽然这个问题已在几年前发布,但当有人正在寻找相同的情景时,它仍然有效。
最近[2015] CodeProject文章用示例代码解释了细节和图形表示的差异。它没有直接关注EF,但仍然希望它会有更大的帮助:
List vs IEnumerable vs IQueryable vs ICollection vs IDictionary