实体框架查询缺少筛选的索引WHERE BIT字段=0
本文关键字:BIT WHERE 字段 索引 查询 框架 筛选 实体 | 更新日期: 2023-09-27 18:01:08
我注意到实体框架使用负布尔过滤器转换LINQ查询,这样生成的查询计划就不会使用过滤索引。例如,查询:
context.Foo.Count(f => !f.IsActive)
生成SQL语句:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Foos] AS [Extent1]
WHERE [Extent1].[IsActive] <> cast(1 as bit)
) AS [GroupBy1]
请注意,WHERE
子句使用[IsActive] <> cast(1 as bit)
,而不是更直观的[IsActive] = 0
。当使用筛选索引时,这会成为一个问题。上述查询的计划将不使用以下索引:
CREATE INDEX IX_Foo_IsActive ON Foos (IsActive) WHERE (IsActive = 0)
我怀疑EF以这种方式生成查询的原因与DB null语义有关,但即使在不可为null的位字段中也会发生这种情况。我已经验证了用EF的语法(IsActive <> 1
(编写过滤索引可以解决这个问题,但这会破坏使用更常见语法的任何非EF查询。
有更好的工作吗?
完整的示例程序如下:http://dotnetfiddle.net/3kZugt.上面使用的实体类型是:
public class Foo
{
public int Id { get; set; }
public bool IsActive { get; set; }
}
由于某种奇怪的原因,有时我们看不到真正明显的东西,这并不罕见:将DB谓词直接翻译为C#谓词,即
WHERE IsActive = 0
被翻译成
f => f.IsActive = false
你必须停止用C#思考,开始用SQL思考;(