【问题标题】:IEnumerable<T>.Count() vs List<T>.Count with Entity FrameworkIEnumerable<T>.Count() 与 List<T>.Count 与实体框架
【发布时间】:2013-08-12 21:17:18
【问题描述】:

我正在使用 Entity Framework 检索项目列表,如果检索到一些项目,我会对它们进行处理。

var items = db.MyTable.Where(t => t.Expiration < DateTime.Now).ToList();
if(items.Count != 0)
{
    // Do something... 
}

if 语句也可以写成

if(items.Count() != 0)
{
    // Do something... 
}

在第一种情况下,.CountList&lt;T&gt;.Count 属性。在第二种情况下,.Count()IEnumerable&lt;T&gt;.Count() 扩展方法。

虽然这两种方法都达到了相同的结果,但是,是一种比另一种更受欢迎吗? (可能在性能上有一些差异?)

【问题讨论】:

  • Enumerable.Count 的优点是以后可以在不破坏代码的情况下更改序列的类型。但请注意Any 更好,因为Count() 枚举整个序列,如果它不是一个集合,而Any 停止在第一个项目。它也更具可读性。
  • @TimSchmelter 但是如果你不改变序列的类型它有缺点:)
  • @lazyberezovsky:唯一的缺点是它经常被使用,即使Any 会更好(见我的编辑)。
  • @lazyberezovsky:那是微优化。除此之外,在返回所有记录的实体框架查询上使用Count() 只是为了知道是否有一条记录,that 确实效率低下。另外,Any 建议我想知道是否有一个项目,而不是有多少项目。所以它也更具可读性。
  • 重要的是要明白,一旦你把ToList 扔进去,你就不能再享受延迟查询的好处了。您现在使用的是 LINQ-to-Objects,而不是使用 LINQ-to-Entities 提供程序。有许多重要的区别,例如 Count() 推迟到底层实现而不是被转换为 SQL,以及字符串比较不再区分大小写。

标签: linq entity-framework extension-methods


【解决方案1】:

Enumerable.Count&lt;T&gt;IEnumerable&lt;T&gt; 的扩展方法)如果底层类型是ICollection&lt;T&gt;,则只调用Count,所以对于List&lt;T&gt; 没有区别。

Queryable.Count&lt;T&gt;IQueryable&lt;T&gt; 的扩展方法)将使用底层查询提供程序,这在许多情况下会将计数向下推到实际 SQL,这比计算内存中的对象。

如果应用了过滤器(例如Count(i =&gt; i.Name = "John"))或基础类型不是ICollection&lt;T&gt;,则枚举集合以计算计数。

一个比另一个更受欢迎?

我通常更喜欢使用 Count(),因为 1) 它更便携(底层类型可以是任何实现 IEnumerable&lt;T&gt;IQueryable&lt;T&gt; 的类型)并且 2) 如果需要,以后添加过滤器更容易。

正如 Tim 在他的评论中所说,我也更喜欢使用 Any()Count() &gt; 0,因为它不必实际计算项目 - 它只会检查一项是否存在。相反,我使用!Any() 而不是Count() == 0

【讨论】:

    【解决方案2】:

    这取决于底层集合以及 Linq 将从何处提取。例如,如果它是 SQL,那么使用 .ToList() 将导致查询拉回整个列表,然后对其进行计数。但是,.Count() 扩展方法会将其转换为数据库端的 SQL COUNT 语句。在这种情况下会有明显的性能差异。

    对于标准列表或集合,如 D. Stanley 的回答中所述。

    【讨论】:

      【解决方案3】:

      我会说这取决于if 块内发生的事情。如果您只是进行检查以确定是否对基础枚举执行一系列操作,那么无论如何都可能不需要它。只需遍历枚举(也省略ToList)。如果你没有在 if 块中使用集合,那么你应该避免使用 ToList 并且绝对使用 Any 而不是任何 Count/Count() 方法。

      一旦您执行了ToList,那么您将不再使用实体框架,我希望Count() 只比Count 慢一点,因为如果基础集合是ICollection&lt;T&gt;,它会遵从这一点执行。唯一的开销是确定它是否实现了该接口。

      http://msdn.microsoft.com/en-us/library/bb338038.aspx

      备注: 如果源的类型实现ICollection&lt;T&gt;,则该实现用于获取元素的计数。否则,此方法确定计数。

      【讨论】:

      • 你能详细说明一下If you're simply doing the check to determine whether to perform a sequence of operations on the underlying enumeration, then it's probably not needed in any event.吗?
      • 好吧,如果你的检查只是if (items.Any()) { foreach (var item in items) { .... } },那么你不需要先检查。如果集合中没有元素,foreach 循环也同样有效。
      猜你喜欢
      • 2011-12-01
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多