实体框架中的 ICollection<T> 与 List<T>
Posted
技术标签:
【中文标题】实体框架中的 ICollection<T> 与 List<T>【英文标题】:ICollection<T> Vs List<T> in Entity Framework 【发布时间】:2011-12-01 03:13:37 【问题描述】:在开始设计一些实体框架应用程序之前,我只看了一些网络广播。我真的没有阅读那么多文档,我觉得我现在正在为此受苦。
我在课堂上一直使用List<T>
,效果很好。
现在我已经阅读了一些文档,它指出我应该使用ICollection<T>
。我改成了这个,它甚至没有引起模型上下文的改变。这是因为List<T>
和ICollection<T>
都继承了IEnumerable<T>
,而这正是EF 真正需要的吗?
但是,如果是这种情况,为什么 EF 文档没有说明它需要 IEnumerable<T>
而不是 ICollection<T>
?
无论如何,我所做的有什么缺点,还是应该改变它?
【问题讨论】:
【参考方案1】:尽管该问题已在几年前发布,但当有人正在寻找相同的场景时,它仍然有效。
最近有一篇 [2015] CodeProject 文章用示例代码解释了许多细节和图形表示的差异。它不直接针对 EF,但仍然希望它能提供更大的帮助:
List vs IEnumerable vs IQueryable vs ICollection vs IDictionary
【讨论】:
【参考方案2】:实体框架将使用ICollection<T>
,因为它需要支持Add
操作,这些操作不是IEnumerable<T>
接口的一部分。
还请注意,您使用了ICollection<T>
,您只是将其公开为List<T>
实现。 List<T>
带来了 IList<T>
、ICollection<T>
和 IEnumerable<T>
。
至于您的更改,尽管List<T>
有效,但通过界面公开是一个不错的选择。接口定义了合约,但没有定义实现。实现可能会改变。例如,在某些情况下,实现可能是HashSet<T>
。 (顺便说一下,这种思维方式不仅可以用于实体框架。一个好的面向对象实践是针对接口而不是实现进行编程。实现可以并且将会改变。)
【讨论】:
所以....只是为了让我进一步理解-List继承IList,继承ICollection,继承IEnumerable? 是的,这就是链条。由于继承层次结构,List<T>
必须实现每个接口(@987654333@、ICollection<T>
、IEnumerable<T>
)。为了补全,IList<T>
还选择了非泛型的IList
、ICollection
和IEnumerable
接口。
谢谢... Ixxx 的某些功能仍然无法理解!但是,您说得有道理,最后一件让我烦恼的事情是,如果另一个 Ixx 继承了 IEnumerable,如果 Ienumerable 是只读的,它如何添加到 IEnumerable 中? ...如果太复杂,别担心,等我有时间,我会尝试启动反射器!
正常的 Linq 操作不会添加或改变事物,它们只是过滤、分组、项目等。仅向前、只读序列是支持这些操作所必需的。当您拥有处理数据持久性的 Entity Framework 之类的 Linq 提供程序时,添加的能力是一个巨大的好处,它需要一个更强大的界面,这就是邀请 ICollection<T>
参加聚会的原因(这个界面也带来了 @987654341 @,所以“正常”的 Linq 操作仍然有效)。
@AnthonyPegram:我认为说三个接口都必须实现是完全不正确的。由于 IList他们选择了他们所做的接口,因为它对您使用 Linq 时 Entity Framework 执行的魔术查询提供了可理解的抽象。
接口之间的区别如下:
IEnumerable<T>
是只读的
您可以向ICollection<T>
添加和删除项目
您可以随机访问(按索引)List<T>
其中,ICollection
和 IEnumerable
很好地映射到数据库操作,因为查询和添加/删除实体是您可能在数据库中执行的操作。
按索引的随机访问也不会映射,因为您必须有一个现有的查询结果才能迭代,否则每次随机访问都会再次查询数据库。另外,索引映射到什么?行号?您想做的行号查询并不多,而且在构建更大的查询时根本没有用。所以他们根本不支持它。
支持ICollection<T>
,并允许您查询和更改数据,所以使用它。
List<T>
开始工作的原因是因为 EF 实现最终返回一个。但那是在查询链的末尾,而不是开头。因此,将您的属性设置为ICollection<T>
将使 EF 创建一堆 SQL 并在最后只返回一个 List<T>
更加明显,而不是对您使用的每一级 Linq 进行查询。
【讨论】:
【参考方案4】:ICollection 与 IEnumerable 的不同之处在于,您实际上可以将项目添加到集合中,而使用 IEnumerable 则不能。因此,例如,在您的 POCO 类中,如果您打算允许将集合添加到,您希望使用 ICollection。将 ICollection 设为虚拟也可以从延迟加载中受益。
【讨论】:
我想了解 - 您可以使用 List以上是关于实体框架中的 ICollection<T> 与 List<T>的主要内容,如果未能解决你的问题,请参考以下文章
为啥 HashSet<T> 没有实现 ICollection?
在 linq to entity 中查询实体的 ICollection