【问题标题】:What is the differences between & and && in EF CoreEF Core 中的 & 和 && 有什么区别
【发布时间】:2019-07-13 20:52:50
【问题描述】:

我知道 && 会使评估短路,因此如果不需要评估 RHS,它就不必评估,但是 EF 呢? & 和 && 之间有什么区别(| 和 || 相同)?性能方面!

【问题讨论】:

  • 如果你需要它用于 ef(Core 与否),并且你想要条件我建议总是使用 && 或 ||。因为目前按位运算符不适合您。

标签: entity-framework entity-framework-core ef-core-2.2


【解决方案1】:

但是 EF 呢? & 和 && 之间有什么区别(| 和 || 相同)?性能方面!

是的,有。

首先,有时 EF Core 使用client evaluation,所以不能短路。

其次,即使在使用服务器评估时,EF Core 也会以不同的方式翻译它们。例如,这里是 SqlServer 的翻译:

LINQ             SQL
==============   ============ 
expr1 && expr2   expr1 AND expr2
expr1 & expr2    (expr1 & expr2) = 1

这是否影响性能取决于数据库查询优化器,但第一个看起来通常更好。并且一些不支持bool 类型的数据库提供程序可能会生成非常低效的翻译,甚至无法翻译& / | 谓词。

简而言之,最好始终在 LINQ 查询中使用逻辑 &&|| 运算符。

【讨论】:

  • 太棒了!但是没看懂这行so it can't be short-circuited.
  • @TanvirArjel 我的意思是,在客户端执行时,它使用与相应 C# 代码相同的评估规则。例如&&|| 会短路,&| 不会。
  • 我明白了!但是如果 sql server expr1 AND expr2 的行为方式与 C# expr1 && expr2 不同?或其他任何东西。
  • @TanvirArjel 查询的评估方式取决于数据库查询优化器及其创建的查询执行计划。他们被允许做很多事情——重新排序条件(为了使用索引)等等,所以一般来说你的问题是无法回答的。
  • @TanvirArjel 同样,SQL 转换如何影响查询计划是未知的。 SqlServer 可能很聪明并将其视为类似于AND,或者可能不是。例如,甲骨文肯定会在翻译和执行方面遇到问题。关键是,ANDOR 是在 SQL 谓词中表示二进制逻辑条件的自然方式。 SQL 的想法是描述期望的结果,而不是如何 做到这一点。这与 LINQ to Objects 不同,后者的执行取决于您如何编写查询。
【解决方案2】:

根据微软文档:

1.& Operator 支持两种形式:一元地址运算符二元逻辑运算符。

一元地址运算符:

一元& 运算符返回其操作数的地址。有关详细信息,请参阅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.&& Operator 是条件逻辑与运算符,也称为“短路”逻辑与运算符,计算其布尔操作数的逻辑与。如果xy 的计算结果都为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 Core 行为的情况下,@Ivan Stoev 做了很大的解释: Here

【讨论】:

  • 感谢@TanvirArjel 问题是关于 EF 行为
【解决方案3】:

我决定做一个实验:

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')

两者都返回相同的结果。我比较了他们的执行计划,执行 t1 我有“Index Scan”,而执行 t2 我有“Index Seek”。正如 Justin 提到的 (SQL Server Plans : difference between Index Scan / Index Seek) “搜索总是比扫描更好,因为它们在查找数据的方式上更有效”。

所以,使用 | or & 不仅会导致客户端评估,还会影响生成的sql。

谢谢大家!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 2019-04-22
    • 1970-01-01
    • 2015-10-27
    • 2021-10-17
    • 2021-08-13
    • 2017-04-05
    相关资源
    最近更新 更多