EF Core 中 & 和 && 有什么区别
What is the differences between & and && in EF Core
我知道 && 会使评估短路,因此它不必评估 RHS(如果不需要),但是 EF 呢? & 和 &&(| 和 || 相同)之间有什么区别吗?性能方面!
根据 Microsoft 文档:
1.The & Operator 支持两种形式:一元地址运算符 或二元逻辑运算符。
运算符的一元地址:
一元&
运算符returns其操作数的地址。有关详细信息,请参阅 How to: obtain the address of a variable 。地址运算符 &
需要不安全的上下文。
整数逻辑按位与运算符:
对于整数类型,&
运算符计算其操作数的逻辑位 AND
:
uint a = 0b_1111_1000;
uint b = 0b_1001_1111;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000
2.The && Operator 是条件逻辑 AND 运算符,也称为 "short-circuiting" 逻辑 AND 运算符,计算其 bool 操作数的逻辑 AND。如果 x
和 y
的计算结果都为 true
,则 x && y
的结果为真。否则,结果为 false
。如果第一个操作数的计算结果为 false
,则不计算第二个操作数且操作结果为 false
。以下示例演示了该行为:
bool SecondOperand()
{
Console.WriteLine("Second operand is evaluated.");
return true;
}
bool a = false && SecondOperand(); // <-- second operand is not evaluated here
Console.WriteLine(a);
// Output:
// False
bool b = true && SecondOperand(); // <-- second operand is evaluated here
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True
现在在 EF/EF 核心行为的情况下 @Ivan Stoev 解释得很好:
but what about EF? Is there any differences between & and && (same for | and ||)? performance-wise!
是的,有。
首先,EF Core有时使用client evaluation,所以不能短路
其次,即使在使用服务器评估时,EF Core 也会以不同的方式翻译它们。例如,这里是 SqlServer 的翻译:
LINQ SQL
============== ============
expr1 && expr2 expr1 AND expr2
expr1 & expr2 (expr1 & expr2) = 1
这是否会影响性能取决于数据库查询优化器,但第一个看起来通常更好。一些不支持 bool
类型的数据库提供者可能会生成非常低效的翻译,甚至无法翻译 &
/ |
谓词。
简而言之,最好始终在 LINQ 查询中使用逻辑 &&
和 ||
运算符。
我决定做一个实验:
var t1 = _db.Customers
.Where(x => x.FirstName == "james" | x.FirstName == "thomas")
.Select(x=>x.CustomerId).ToList();
对比
var t2 = _db.Customers
.Where(x => x.FirstName == "james" || x.FirstName == "thomas")
.Select(x => x.CustomerId).ToList();
t1 被执行为:
SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE (CASE
WHEN [x].[FirstName] = N'james'
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END | CASE
WHEN [x].[FirstName] = N'thomas'
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END) = 1
和 t2 为:
SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE [x].[FirstName] IN (N'james', N'thomas')
两个returns相同的结果。我比较了他们的执行计划,执行 t1 我有 "Index Scan" 而执行 t2 我有 "Index Seek"。正如贾斯汀提到的 (SQL Server Plans : difference between Index Scan / Index Seek) "Seeks are always better to have than scans as they are more efficient in the way it looks data up".
所以,使用 | or & 不仅会导致客户端评估,还会影响生成的 sql。
谢谢大家!
我知道 && 会使评估短路,因此它不必评估 RHS(如果不需要),但是 EF 呢? & 和 &&(| 和 || 相同)之间有什么区别吗?性能方面!
根据 Microsoft 文档:
1.The & Operator 支持两种形式:一元地址运算符 或二元逻辑运算符。
运算符的一元地址:
一元&
运算符returns其操作数的地址。有关详细信息,请参阅 How to: obtain the address of a variable 。地址运算符 &
需要不安全的上下文。
整数逻辑按位与运算符:
对于整数类型,&
运算符计算其操作数的逻辑位 AND
:
uint a = 0b_1111_1000;
uint b = 0b_1001_1111;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000
2.The && Operator 是条件逻辑 AND 运算符,也称为 "short-circuiting" 逻辑 AND 运算符,计算其 bool 操作数的逻辑 AND。如果 x
和 y
的计算结果都为 true
,则 x && y
的结果为真。否则,结果为 false
。如果第一个操作数的计算结果为 false
,则不计算第二个操作数且操作结果为 false
。以下示例演示了该行为:
bool SecondOperand()
{
Console.WriteLine("Second operand is evaluated.");
return true;
}
bool a = false && SecondOperand(); // <-- second operand is not evaluated here
Console.WriteLine(a);
// Output:
// False
bool b = true && SecondOperand(); // <-- second operand is evaluated here
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True
现在在 EF/EF 核心行为的情况下 @Ivan Stoev 解释得很好:
but what about EF? Is there any differences between & and && (same for | and ||)? performance-wise!
是的,有。
首先,EF Core有时使用client evaluation,所以不能短路
其次,即使在使用服务器评估时,EF Core 也会以不同的方式翻译它们。例如,这里是 SqlServer 的翻译:
LINQ SQL
============== ============
expr1 && expr2 expr1 AND expr2
expr1 & expr2 (expr1 & expr2) = 1
这是否会影响性能取决于数据库查询优化器,但第一个看起来通常更好。一些不支持 bool
类型的数据库提供者可能会生成非常低效的翻译,甚至无法翻译 &
/ |
谓词。
简而言之,最好始终在 LINQ 查询中使用逻辑 &&
和 ||
运算符。
我决定做一个实验:
var t1 = _db.Customers
.Where(x => x.FirstName == "james" | x.FirstName == "thomas")
.Select(x=>x.CustomerId).ToList();
对比
var t2 = _db.Customers
.Where(x => x.FirstName == "james" || x.FirstName == "thomas")
.Select(x => x.CustomerId).ToList();
t1 被执行为:
SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE (CASE
WHEN [x].[FirstName] = N'james'
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END | CASE
WHEN [x].[FirstName] = N'thomas'
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END) = 1
和 t2 为:
SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE [x].[FirstName] IN (N'james', N'thomas')
两个returns相同的结果。我比较了他们的执行计划,执行 t1 我有 "Index Scan" 而执行 t2 我有 "Index Seek"。正如贾斯汀提到的 (SQL Server Plans : difference between Index Scan / Index Seek) "Seeks are always better to have than scans as they are more efficient in the way it looks data up".
所以,使用 | or & 不仅会导致客户端评估,还会影响生成的 sql。
谢谢大家!