在检查BIT列时,LINQ生成了奇怪的SQL

本文关键字:SQL BIT 检查 列时 LINQ | 更新日期: 2023-09-27 17:58:18

我有以下LINQtoSQL语句

from t1 in __table1
join t2 in __table2 on t1.Id equals t2.OtherTableId
where t2.BranchId == branchId
      && !t1.IsPersonal
select t1.Id

这将生成以下SQL

SELECT DISTINCT [t0].[Id]
FROM [__table1] AS [t0]
INNER JOIN [__table2] AS [t1] ON [t0].[Id] = [t1].[OtherTableId]
WHERE ([t1].[BranchId] = @p0) AND (NOT ([t0].[IsPersonal] = 1))

现在我的问题是:

(NOT ([t0].[IsPersonal] = 1))

我怎么能写LINQ只说

[t0].[IsPersonal] = 0

注意:IsPersonal不可为null。

在检查BIT列时,LINQ生成了奇怪的SQL

Edit:我可能比优化器更聪明,但不幸的是,当使用Linq2Sql时,当"filter criteria"是一个参数时,就不会使用筛选的索引——这就是它的作用。所以最后我放弃了,转而使用存储过程。替代方案太恶心了。

注意:生成的SQL在没有索引提示的情况下使用筛选的索引,但由于我在SSMS中运行,因此查询计划缓存不适用。


啊哈!最后设法智胜了优化器。

WHERE object.Equals(t.Voided, 0)

WHERE object.Equals(t.Voided, "false")

哪个生成

WHERE ([t0].[Voided] = @p0)

@p0以字符串或数字的形式发送,SQL Server将其转换为布尔值。

这似乎适用于过滤索引(和强制提示),这就是我首先需要绕过优化器的原因。

注意:由于某些原因,有时"0"会给出布尔解析错误,因此0"false"可能更好。可能取决于您的查询的一些细微之处。

我更喜欢0,因为"false"最终变成了varchar(8000),这有点过头了!

是的,所以我想我已经想通了。以下线路

t1.IsPersonal == false

被优化为

!t1.IsPersonal

这反过来又被翻译成

(NOT ([t0].[IsPersonal] = 1))

似乎优化器应该"责怪"