EF 在使用 StartsWith 过滤时不使用 SQL 索引

Posted

技术标签:

【中文标题】EF 在使用 StartsWith 过滤时不使用 SQL 索引【英文标题】:EF not using SQL index when filtering with StartsWith 【发布时间】:2012-11-27 12:34:58 【问题描述】:

以下 LINQ 查询过滤带有 StartsWith() 谓词的行:

db.Pictures.Where(pic => pic.Filename.StartsWith(path)).Count();

转换为以下 SQL(来自 SQL Server Profiler):

exec sp_executesql N'SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[Pictures] AS [Extent1]
    WHERE [Extent1].[Filename] LIKE @p__linq__0 ESCAPE N''~''
)  AS [GroupBy1]',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'10429\2\6\%'

Filename 列的类型为 VARCHAR(255) 并已编入索引。 但是,由于ESCAPE N'~'中的N,查询不使用索引。

在查询执行计划中我可以看到一个警告:

表达式中的类型转换 (CONVERT_IMPLICIT(NVARCHAR(255), [Extent1].[Filename], 0)) 可能会影响查询计划选择中的“CardinalityEstimate”

删除 N 后查询运行良好(使用索引)。

我该如何解决这个问题?

(一个明显的解决方案可能是将列的类型更改为 NVARCHAR,但这似乎并不理想,因为我实际上不需要存储 unicode 数据)

【问题讨论】:

您是否尝试将Filename 显式映射为 VARCHAR? 【参考方案1】:

您需要将模型也设置为 varchar。您可以通过在上下文中覆盖 OnModelCreating 来配置它。

protected override void OnModelCreating(DbModelBuilder modelBuilder)

    modelBuilder.Entity<Picture>().Property(p => p.Filename).IsUnicode(false);

【讨论】:

我忘了说明我使用的是代码优先,但你猜对了!

以上是关于EF 在使用 StartsWith 过滤时不使用 SQL 索引的主要内容,如果未能解决你的问题,请参考以下文章

在 Gatsby 的 graphQL 查询中使用 begin With 或 startsWith 过滤器

Pyspark 过滤器使用列表中的startswith

OData:通配符(startswith)过滤 url 请求中的数字(ID)字段

Angular JS 'Startswith' 自定义过滤器

EF4 与 SQL Compact 4,rowversion 在保存时不更新

按包含过滤,然后按startsWith排序