C# Where().Count()和Count()之间的差异
以上面的例子为例,我列出了30岁以上的员工名单 方法1和方法2的区别是什么?C# Where().Count()和Count()之间的差异,c#,linq,entity-framework,C#,Linq,Entity Framework,以上面的例子为例,我列出了30岁以上的员工名单 方法1和方法2的区别是什么? 你喜欢哪一种?为什么?为了可读性,我更喜欢第二种方法。如果您查看生成的sql代码,它是相同的 方法1: using (DBEntities db = new DBEntities()) { var employeeAgedAbove30 = db.Employees.Where(s => s.Age > 30).Count(); // Method 1 employeeAgedAbove30
你喜欢哪一种?为什么?为了可读性,我更喜欢第二种方法。如果您查看生成的sql代码,它是相同的 方法1:
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
}
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
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
00:00:00.0019229
00:00:00.0007023
-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0
SQL
db.TblEmployees.Where (t =>t.Age>30).Count ()
db.TblEmployees.Count (t =>t.Age>30)
方法2:
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
}
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
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
00:00:00.0019229
00:00:00.0007023
-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0
SQL
db.TblEmployees.Where (t =>t.Age>30).Count ()
db.TblEmployees.Count (t =>t.Age>30)
归根结底,这更多的是个人偏好。对于不习惯linq的人来说,在计数之前使用where子句可能更具可读性
编辑1
在旁注上。是的,生成sql是相同的。但是IL代码在一个地方是不同的。应用计数和where时
方法1:
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
}
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
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
00:00:00.0019229
00:00:00.0007023
-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0
在我的测试中,所有员工都是空的。我得到这个结果:
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);
在性能上没有差别。这只是关于代码的可读性 我创建了一个表并在中运行这两个查询。输出结果如下: 方法1的SQL:
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
}
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
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
00:00:00.0019229
00:00:00.0007023
-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0
执行时间:00:00.279
方法2的SQL:
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
}
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
GO
-- Region Parameters
DECLARE @p0 Int = 30
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [tblEmployees] AS [t0]
WHERE [t0].[Age] > @p0
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
00:00:00.0019229
00:00:00.0007023
-- Region Parameters
DECLARE @p0 Int = 1
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Employees] AS [t0]
WHERE [t0].[Type] = @p0
执行时间:00:00.275
在这里,您可以看到LINQ生成的SQL没有差别,执行时间也有细微差别。第一个将首先过滤记录,然后计数,第二个将执行相同的操作。我认为,在itRun SQL Profiler(假设您使用MSSQL作为DB后端)或类似的操作中,第二个where子句位于itRun SQL Profiler中,捕获两个查询并比较它们。它们都被转换为相同的SQL(来自LINQPad)。@amarduplantier为什么不自己尝试一下呢。使用秒表测量时间:)顺便说一句,这两个语句都应该做同样的操作,了解详细信息。所以他们有
Where
只是为了可读性?我应该像其他人说的那样检查执行时间的差异吗?执行时间在我的项目中非常重要。@amarduplantier:更新了答案