Linq Count方法与性能

8

我在项目中广泛使用Linq,目前性能良好。我只有一个疑问,如果我像这样使用了Linq:

var getData = objData.where(obj => obj.isDelete ==false)
if (getData != null && getData.Count() > 0)
   foreach(xyz as obj in getdata.ToList())
   {
      //some operation
   }

getData.Count()和getdata.ToList()在对象上执行两个不同的获取操作吗?或者按照延迟加载的概念,当执行getData.Count()时,不会执行.ToList的操作。

如果不是这样,那么我应该删除Count条件,这样会提高性能吗?

我正在使用Enterprise Library 5.0访问器方法从数据库中获取数据List lstpack = new List();

            var accessor = _sqlDatabase.CreateSprocAccessor<PackageForClient>("PackageForClientApp", MapBuilder<PackageForClient>
                      .MapAllProperties()
                      .Build()
               );

            var Data = accessor.Execute(startdate, enddate,beinh);
            if (Data != null) //&& Data.Count() > 0 //This has been removed as it is doing an extra fetch
                lstpack = Data.ToList<PackageForClient>();

现在返回列表。
1个回答

13

很难确定,因为我们不知道getData是什么,但是:

  • 是的,它们有可能是完全独立的操作。
  • 通常来说,使用Any()而不是Count() > 0会更高效,特别是在LINQ to Objects中。
  • 如果需要列表,调用ToList的成本相对较低 - 只需在需要时这样做。
  • 如果您真的不需要它作为列表,那就直接迭代(如果没有数据,您永远不会进入循环体)。
  • Where永远不会返回null。

换句话说,我可能会写成:

foreach (Obj xyz in objData.Where(obj => !obj.isDelete))
{
   //some operation
}

太好了!谢谢。这里的getData是由Enterprise Library 5.0结果集返回的对象列表。惊讶地发现它执行了存储过程两次,一次是在调用getData的Count方法时,另一次是在使用ToList时。 - Deepesh
@Deepesh:你为什么对此感到惊讶?getData不是对象列表 - 它是一个查询。调用ToList会将其转换为对象列表。 - Jon Skeet
是的,它会生效,但我很惊讶地看到数据库操作被执行了两次,一次用于计数,另一次用于列表。这意味着存储过程被执行了两次,理想情况下,当执行计数时,结果集应该进入内存,而不是在调用ToList()时再次执行。 - Deepesh
@Deepesh:如果你想将所有结果存入内存,那么ToList正是为此而生。一些LINQ提供程序会在上下文中缓存查询结果,但这取决于所涉及的提供程序的详细信息。 - Jon Skeet
非常感谢@Jon在这方面的帮助,解决了我的疑惑。再次感谢。 - Deepesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接