如何在Linq中实现类似于SQL中的Like %的功能?

412

我有一个在SQL中的存储过程,我想把它转换成Linq:

SELECT O.Id, O.Name as Organization
FROM Organizations O
JOIN OrganizationsHierarchy OH ON O.Id=OH.OrganizationsId
where OH.Hierarchy like '%/12/%'

我最关心的是这行代码:

where OH.Hierarchy like '%/12/%'

我有一个存储类似于/1/3/12/层次结构的列,所以我只需使用%/12 /%进行搜索。

我的问题是,Linq或.NET中有什么等效于使用百分号的方法?


1
您的问题在 [tag:like-operator] 标签下至少有 5 个投票。我可以请求您提出将 [tag:sql-like] 作为 synonym 的建议吗? - Kermit
不清楚是否需要LINQ-to-Objects的等效项。如果需要,那么linq-to-entities标签就不相关且会令人困惑。 - Gert Arnold
15个回答

589
.Where(oh => oh.Hierarchy.Contains("/12/"))

你也可以使用.StartsWith()或者.EndsWith()


5
使用 StartsWith() 或 EndsWith() 会触发查询吗?我的意思是,代码会被转换成查询还是结果将在从数据库检索后在对象中过滤? - Novice
5
StartsWith()和EndsWith()是谓词/筛选器的一部分。执行仍然被延迟。 - andleer
2
尝试过后出现了NullReferenceException: 对象引用未设置为对象实例。所以在我的情况下,当a.Address1.StartsWith(Address1) 且a.Address1为null时,它就无法工作。 - MikeT
12
StartsWith("abc") 会被转换成 LIKE 'abc%',而 EndsWith("abc") 则会被转换成 LIKE '%abc' - Simon_Weaver
25
无法理解为什么这个用于处理字母的用例无法工作,然后意识到我的愚蠢...如果您想忽略大小写,请不要忘记使用 .ToLower().Contains()等方法。当然,是否需要这样做取决于您是否希望使用不区分大小写的排序方式来模拟数据库中的LIKE操作。 - Adam Knights
显示剩余10条评论

262
使用这个:
from c in dc.Organization
where SqlMethods.Like(c.Hierarchy, "%/12/%")
select *;

23
如果您想使用Like命令提供的更复杂的模式匹配,这将非常有帮助。例如,如果您想检查任何两个数字(而不是12),则可以使用此表达式:SqlMethods.Like(c.Hierarchy,"% / [0-9] [0-9] /%")。另外,请查看http://msdn.microsoft.com/en-us/library/aa933232(SQL.80).aspx。 - viggity
1
如果您想允许高级用户自行添加昂贵的初始“%”,则这也非常有用,使用StartsWith或Contains无法为高级用户提供此灵活性。 - Simon_Weaver
9
如何使用“点符号”使用 SqlMethods - dan-gph
16
请注意需要包含 System.Data.Linq.SqlClient 命名空间。 - johna
3
我找不到 System.Data.Linq.SqlClient,尽管我可以添加 System.Data.Linq。它已经弃用了吗? - Burak Karakuş
显示剩余2条评论

43

我假设你正在使用Linq-to-SQL*(见下面的注释)。如果是这样,请使用string.Contains、string.StartsWith和string.EndsWith生成使用SQL LIKE运算符的SQL。

from o in dc.Organization
join oh in dc.OrganizationsHierarchy on o.Id equals oh.OrganizationsId
where oh.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }
或者
from o in dc.Organization
where o.OrganizationsHierarchy.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }

注意: * = 如果您正在使用ADO.Net Entity Framework(EF / L2E)在.net 3.5中,请注意它不会像Linq-to-SQL一样进行相同的翻译。虽然L2S可以正确翻译,但L2E v1(3.5)将转换为一个t-sql表达式,这将强制对您查询的表执行完整的表扫描,除非在where子句或连接过滤器中有另一个更好的鉴别器。
更新:在EF / L2E v4(.net 4.0)中已经修复了这个问题,因此它会像L2S一样生成SQL LIKE。


不需要使用 @ 符号转义字符串,但我意识到这可能只是一个好的约定。 - andleer

29
如果你正在使用VB.NET,那么答案将是“*”。这是你的where子句应该如何写...
Where OH.Hierarchy Like '*/12/*'

注意:"*"匹配零个或多个字符。这里是Like运算符的MSDN文章


VB 的 Like 运算符是否会转换为 L2S 调用?(我不知道。) - andleer
8
当在LINQ查询表达式中使用VB的"Like"运算符时,它会被翻译成相应的SQL的"like"运算符。此外,VB的"Like"运算符并不仅限于查询表达式。 - robertz
1
我发现它存在于LINQ操作之外。很不错。+1 - andleer

8

我也觉得indexOf对我很有用。

var result = from c in SampleList
where c.LongName.IndexOf(SearchQuery) >= 0
select c;

1
这应该是被接受的答案。在SQL中,IndexOf被翻译为CHARINDEX。这可能比LIKE快。但除此之外,它还提供了构建搜索查询的可能性,例如'%some%thing%'。其中'some'必须位于'thing'之前,使用Contains无法做到这一点。 - user4864425
1
我非常喜欢当我需要的答案已经有8年历史并且被藏在接受答案的几层下面。简单来说,这个方法有效,而.Contains(@"/12/")和其他类似的方法却不行。非常感谢! - IdusOrtus

7

.NET Core现在拥有EF.Functions.Like

  var isMatch = EF.Functions.Like(stringThatMightMatch, pattern);

1
你能解释一下如何使用这个来解决 OP 的问题吗? - Robert Columbia
看看LP的回答,它只是SqlMethods的核心版本。 - kofifus
1
这个答案应该包含一个可操作的示例,展示如何使用这个函数。 - FoxDeploy

4
使用以下代码:
try
{
    using (DatosDataContext dtc = new DatosDataContext())
    {
        var query = from pe in dtc.Personal_Hgo
                    where SqlMethods.Like(pe.nombre, "%" + txtNombre.Text + "%")
                    select new
                    {
                        pe.numero
                        ,
                        pe.nombre
                    };
        dgvDatos.DataSource = query.ToList();
    }
}
catch (Exception ex)
{
    string mensaje = ex.Message;
}

3

如果您不匹配数字字符串,始终最好使用通用情况:

.Where(oh => oh.Hierarchy.ToUpper().Contains(mySearchString.ToUpper()))

2

我总是这样做:

from h in OH
where h.Hierarchy.Contains("/12/")
select h

我知道我没有使用like语句,但是在后台它能正常工作,这是否转换成了一个带有like语句的查询。


你的回答与被接受的回答(7年前回答)或其他回答有何不同?它增加了什么价值? - David Ferenczy Rogožan
1
@DawidFerenczy 这个答案适用于“from foo in bar”查询语法,而被接受的答案则不适用。 - nasch

2
System.Data.Linq.SqlClient.SqlMethods.Like("mystring", "%string")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接