Where()。Count()和Count()之间的区别

时间:2014-05-26 06:18:07

标签: c# linq entity-framework

using (DBEntities db = new DBEntities())
{
   var employeeAgedAbove30 = db.Employees.Where(s => s.Age > 30).Count(); // Method 1

   employeeAgedAbove30 = db.Employees.Count(s => s.Age > 30); // Method 2

}

考虑上面的例子,我列出了30岁以上的员工。

方法1和方法2有什么区别? 你更喜欢哪一个?为什么?

2 个答案:

答案 0 :(得分:14)

我更倾向于使用第二种方法来实现可读性。如果你看一下生成的sql代码,它就是一样的。

方法1:

db.TblEmployees.Where (t =>t.Age>30).Count ()

<强> SQL

-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO

方法2:

db.TblEmployees.Count (t =>t.Age>30)

<强> SQL

-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0

在一天结束时,更多的是个人偏好。对于不习惯linq的人来说,在计数之前使用where子句可能更具可读性。

修改1

旁注。是的,生成sql是一样的。但IL代码在一个地方是不同的。在应用计数和地点时。

方法1:

IL_0001:  ldarg.0     
IL_0002:  stloc.0     // db
IL_0003:  ldloc.0     // db
IL_0004:  callvirt    LINQPad.User.TypedDataContext.get_TblEmployees
IL_0009:  ldtoken     LINQPad.User.TblEmployees
IL_000E:  call        System.Type.GetTypeFromHandle
IL_0013:  ldstr       "t"
IL_0018:  call        System.Linq.Expressions.Expression.Parameter
IL_001D:  stloc.1     // CS$0$0000
IL_001E:  ldloc.1     // CS$0$0000
IL_001F:  ldtoken     LINQPad.User.TblEmployees.get_Age
IL_0024:  call        System.Reflection.MethodBase.GetMethodFromHandle
IL_0029:  castclass   System.Reflection.MethodInfo
IL_002E:  call        System.Linq.Expressions.Expression.Property
IL_0033:  ldc.i4.s    1E 
IL_0035:  box         System.Int32
IL_003A:  ldtoken     System.Int32
IL_003F:  call        System.Type.GetTypeFromHandle
IL_0044:  call        System.Linq.Expressions.Expression.Constant
IL_0049:  ldtoken     System.Nullable<System.Int32>
IL_004E:  call        System.Type.GetTypeFromHandle
IL_0053:  call        System.Linq.Expressions.Expression.Convert
IL_0058:  call        System.Linq.Expressions.Expression.GreaterThan
IL_005D:  ldc.i4.1    
IL_005E:  newarr      System.Linq.Expressions.ParameterExpression
IL_0063:  stloc.2     // CS$0$0001
IL_0064:  ldloc.2     // CS$0$0001
IL_0065:  ldc.i4.0    
IL_0066:  ldloc.1     // CS$0$0000
IL_0067:  stelem.ref  
IL_0068:  ldloc.2     // CS$0$0001
IL_0069:  call        System.Linq.Expressions.Expression.Lambda
IL_006E:  call        System.Linq.Queryable.Where
IL_0073:  call        System.Linq.Queryable.Count

方法2:

IL_0001:  ldarg.0     
IL_0002:  stloc.0     // db
IL_0003:  ldloc.0     // db
IL_0004:  callvirt    LINQPad.User.TypedDataContext.get_TblEmployees
IL_0009:  ldtoken     LINQPad.User.TblEmployees
IL_000E:  call        System.Type.GetTypeFromHandle
IL_0013:  ldstr       "t"
IL_0018:  call        System.Linq.Expressions.Expression.Parameter
IL_001D:  stloc.1     // CS$0$0000
IL_001E:  ldloc.1     // CS$0$0000
IL_001F:  ldtoken     LINQPad.User.TblEmployees.get_Age
IL_0024:  call        System.Reflection.MethodBase.GetMethodFromHandle
IL_0029:  castclass   System.Reflection.MethodInfo
IL_002E:  call        System.Linq.Expressions.Expression.Property
IL_0033:  ldc.i4.s    1E 
IL_0035:  box         System.Int32
IL_003A:  ldtoken     System.Int32
IL_003F:  call        System.Type.GetTypeFromHandle
IL_0044:  call        System.Linq.Expressions.Expression.Constant
IL_0049:  ldtoken     System.Nullable<System.Int32>
IL_004E:  call        System.Type.GetTypeFromHandle
IL_0053:  call        System.Linq.Expressions.Expression.Convert
IL_0058:  call        System.Linq.Expressions.Expression.GreaterThan
IL_005D:  ldc.i4.1    
IL_005E:  newarr      System.Linq.Expressions.ParameterExpression
IL_0063:  stloc.2     // CS$0$0001
IL_0064:  ldloc.2     // CS$0$0001
IL_0065:  ldc.i4.0    
IL_0066:  ldloc.1     // CS$0$0000
IL_0067:  stelem.ref  
IL_0068:  ldloc.2     // CS$0$0001
IL_0069:  call        System.Linq.Expressions.Expression.Lambda
IL_006E:  call        System.Linq.Queryable.Count

修改2

解决评论。是的,我会检查执行时间,看看有什么意义。我仍然相信第二个会更快。但你必须检查。如果它是代码的性能关键部分。从数据库方面,我会检查查询的执行计划。它可能会在Age列上添加索引。

编辑3

您还可以测量执行命令所需的时间。这是使用Stopwatch类的简短演示:

var st=new Stopwatch();
st.Start();
db.TblEmployees.Where (t =>t.Age>30).Count ();
st.Stop();
Console.WriteLine(st.Elapsed);
st.Restart();
db.TblEmployees.Count (t =>t.Age>30);
st.Stop();
Console.WriteLine(st.Elapsed);

在我的测试中,TblEmployees为空。我得到了这个结果:

00:00:00.0019229
00:00:00.0007023

答案 1 :(得分:1)

性能没有差异。这只是关于代码的可读性。

我创建了一个表并在LINQPad中运行了两个查询。以下是输出:

方法1的SQL:

-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0

执行时间:00:00.279

方法2的SQL:

-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0

执行时间:00:00.275

在这里,您可以看到LINQ生成的SQL与执行时间的微小差异没有区别。