优先用 StartsWith 而非 Contains,因其可命中索引前缀提升性能;Contains 仅适用于必要模糊匹配,且需注意空值、大小写、数据库兼容性及 SQL 注入防护。

用 Contains 还是 StartsWith?看场景选对方法
模糊查询在 C# 里不是靠“通配符语法”实现的,而是靠字符串方法配合 LINQ 或 EF 的翻译规则。直接写 "%abc%" 在 EF Core 里会报错或查不到——它不识别 SQL 风格通配符。
常见错误现象:Where(x => x.Name.Contains("abc")) 在内存中执行(触发 ToList() 后才过滤),导致全表拉到客户端再筛,性能崩盘。
- 数据库端模糊:EF Core 6+ 支持
Contains、StartsWith、EndsWith翻译成LIKE,但必须确保字段没被提前转成IEnumerable - 大小写敏感问题:SQL Server 默认不区分,PostgreSQL 默认区分;EF Core 不自动加
COLLATE,要查前确认数据库排序规则 - 空值陷阱:
Contains(null)抛ArgumentNullException,得先判空:!string.IsNullOrEmpty(keyword) && x.Name.Contains(keyword)
EF Core 中 LIKE 模式匹配要手动拼接?别硬来
想实现 LIKE "ab%c_" 这种带通配符的自由匹配?EF Core 原生不支持直接传 % 字符进 Contains——它会把 % 当普通字符,不是通配符。
正确做法是用 EF.Functions.Like(仅限 SQL Server / PostgreSQL)或数据库函数映射:
- SQL Server 示例:
context.Users.Where(x => EF.Functions.Like(x.Name, $"%{keyword}%")) - PostgreSQL 需启用扩展:
EF.Functions.ILike(x.Name, $"%{keyword}%")(注意大小写不敏感) - SQLite 不支持
Like函数,只能退回到Contains+ 确保索引存在,或改用Fts5全文检索 - 参数化防注入:所有变量必须通过插值或参数传入,禁止字符串拼接 SQL
性能掉坑:没加索引 or 用了函数导致索引失效
WHERE Name LIKE "%abc"(前导通配符)在绝大多数数据库上无法走 B-Tree 索引,等价于全表扫描。这不是 C# 的锅,但你得知道后果。
- 能用
StartsWith就别用Contains:前者可命中索引前缀,后者基本不可 - SQL Server 上,给字段加全文索引后,改用
EF.Functions.FreeText或EF.Functions.Contains(注意不是 LINQ 的Contains) - PostgreSQL 可建
pg_trgm扩展 +GIST索引加速ILike查询 - EF Core 日志里看生成的 SQL:开
EnableDetailedErrors和日志输出,确认最终语句是否含LIKE而非CHARINDEX或客户端计算
中文分词和拼音搜索怎么搞?别指望 EF Core 自动处理
用户搜“张三”,结果“张珊”“章三”也出来——这是模糊查询,不是分词。EF Core 没内置拼音转换或中文分词能力。
- 简单方案:预存拼音字段(如
PinyinName),查时转拼音再StartsWith - 进阶方案:用 Elasticsearch 或 Apache Lucene 做独立搜索服务,C# 只负责调 API
- 别在 C# 层用
StringComparison.OrdinalIgnoreCase解决中文模糊——它只管大小写,不管形近、音近、错别字 - 第三方库如
HanLP.Net或Pinyin.NET可做运行时转换,但要注意性能开销和线程安全
真正麻烦的从来不是写那行 Contains,而是查完发现慢、不准、漏数据,再回头补索引、改字段、加服务——这些决策点,在写第一行查询前就得想清楚。


















