添加包含字符串的Linq Where子句的问题

本文关键字:子句 问题 Where Linq 字符串 添加 包含 | 更新日期: 2023-09-27 17:51:06

好吧,这种行为真把我难住了。我有一个IQueryable列表,我试图添加Where子句来检查字符串字段是否包含子字符串。当我像这样硬编码搜索字符串时:

sourceList = sourceList.Where(license => license.FileNumber.Contains("S0"))

它按预期工作,并通过在Visual Studio调试器中检查sourceList生成内部查询:

{SELECT [Extent1].[id] AS [id], [Extent1].[FileNumber] AS [FileNumber],
    [Extent1].[LegalLocation] AS [LegalLocation]FROM [dbo].[Licenses]
    AS [Extent1]WHERE [Extent1].[FileNumber] LIKE N'%S0%'}

当我从一个变量中设置搜索值时,奇怪的事情发生了:

string testString = "S0";
sourceList = sourceList.Where(license => license.FileNumber.Contains(testString))

生成内部查询:

{SELECT [Extent1].[id] AS [id], [Extent1].[FileNumber] AS [FileNumber],
    [Extent1].[LegalLocation] AS [LegalLocation]FROM [dbo].[Licenses]
    AS [Extent1]WHERE [Extent1].[FileNumber] LIKE @p__linq__0 ESCAPE N'~'}

注意到末尾LIKE部分的不同吗?我真的很困惑。任何帮助都将非常感激。希望这是一个非常愚蠢的东西。如果它有任何相关性,这是用于从实体框架源过滤数据。

谢谢,杰森

添加包含字符串的Linq Where子句的问题

如果您观察实际的查询,您将看到@p__linq__0实际上被分配了S0值,然后传递给查询。

@p__linq__0 = '%S0%';
... WHERE [Extent1].[FileNumber] LIKE @p__linq__0 ESCAPE N'~'

基本上就像:

... WHERE [Extent1].[FileNumber] LIKE N'%S0%' ESCAPE N'~'

因为它是一个参数,LINQ只是采取了预防措施,添加了ESCAPE子句。它也是一个变量,而不是硬编码的常量,LINQ语句中任何变化的值都是作为参数传递的,而不是直接插入到查询中。

Reference: LIKE (Transact-SQL)

在第二种情况下,LINQ生成一个参数化查询。考虑一下,如果您使用一些DbCommand手动构造一个参数化查询:

OleDbCommand cmd = new OleDbCommand(
     "SELECT * from SomeTable where SomeField like @Param1", con);
cmd.Parameters.Add("@Param1", OleDbType.VarChar).Value = "%SomeField value%";

所以@p__linq__0是由linq生成的参数的名称(而在我的例子中它是@Param1)。

ESCAPE关键字是LIKE表达式的一部分(参见LIKE (Transact-SQL)):

语法

match_expression [ NOT ] LIKE pattern [ ESCAPE escape_character ]

,

escape_character

Is a character that is put in front of a wildcard character to indicate that the    
wildcard should be interpreted as a regular character and not as a wildcard. 
escape_character is a character expression that has no default and must evaluate to 
only one character.

第二个内部查询只是在LIKE子句中使用了一个参数,正如预期的那样。

如果您观察到不同的结果,可能是因为您在一种情况下传递"SO",而在另一种情况下传递"S0"(至少在您的问题中的一些代码中)。