使用Lambda表达式检查字符串值是否包含任何数字

11

我有一个SQL查询,只检索不包含任何数字的名称:

...
WHERE Name NOT LIKE '%[0-9]%'

然而,当尝试在Lambda表达式中使用不同组合来使用此查询时,下面显示的任何组合都不起作用:

.Where(m => !m.EmployeeName.Contains("%[0-9]%")

或者
 .Where(m => !m.EmployeeName.Contains(".*[0-9].*")

我如何在Lambda表达式中使用NOT LIKE方法?

更新:我的Lambda表达式如下所示:

return Json(db.TEmployees
    .Where(m => m.Status == Enums.Status.Active)
    .AsEnumerable()
    .Where(m => !Regex.IsMatch(m.EmployeeName, ".*[0-9].*"))
    .Select(m => new { ID = m.EmployeeID, EmployeeName = m.EmployeeName }), 
        JsonRequestBehavior.AllowGet);


看看这个:https://dev59.com/ik_Ta4cB1Zd3GeqPEd27 - Venki
@Venki,我已经知道了,但我需要一个带有[0-9]的解决方案。请仔细阅读我的问题! - Jack
需要使用ToList()方法来处理JSON数据,请再次查看我的回答 @binary - Alper Tunga Arslan
请勿在问题本身中发布答案,而是发布一个新的回答。 - Kyll
6个回答

5
据我所知,在Linq to Entities中无法应用正则表达式。我的建议是,如果您有其他条件,请先使用它们调用Where方法,然后调用AsEnumerable来使用Linq to Object,这样可以使用正则表达式,以便应用所需的条件:
var query= context.YourDbSet.Where(...)
                            .AsEnumerable()
                            .Where(m => !Regex.IsMatch(m.EmployeeName, @"\d"));

您也可以尝试以下方法:

或者您也可以执行以下操作:

var query= context.YourDbSet.Where(...)
                            .AsEnumerable()
                            .Where(e=>e.!EmployeeName.Any(char.IsDigit));

更新:

第三种解决方案可以使用DbSet.SqlQuery方法来执行原始的SQL查询:

var query= context.YourDbSet.SqlQuery("SELECT * FROM Table WHERE Name NOT LIKE '%[0-9]%'");

将其翻译到您的情境中,可能是这样的:
                     // This column names must match with 
                     //  the property names in your entity, otherwise use *
return Json(db.TEmployees.SqlQuery("SELECT EmployeeID,EmployeeName 
                                    FROM Employees 
                                    WHERE Status=1 AND Name NOT LIKE '%[0-9]%'"), 
           JsonRequestBehavior.AllowGet);// Change the value in the first condition for the real int value that represents active employees

不幸的是,它们中没有一个返回任何记录(即使其他的也是如此)。无论如何,你知道我怎么在这种情况下使用SQL查询来对应我上面的lambda表达式吗(我添加了更新)?有什么想法吗? - Jack
嗨@binary,看看我的更新。 - ocuenca
非常感谢您的帮助。我还在我的问题上发布了方法的最终状态,以便其他人也可以使用它。问候... - Jack

2

EF的能力有限,无法生成您想要的确切SQL。我不知道是否存在特定表达式可以在您的LIKE子句中生成模式[0-9]

支持EF的字符串函数列表已在MSDN上记录。其中没有任何一个可用于确定字符串是否包含任意数字。

其他一些选项是:

  • 在C#中使用您想要的确切SQL并调用ExecuteStoreCommand
  • 从数据库返回比您需要的更多对象,并使用AsEnumerable()在内存中过滤

相应的SQL应该类似于:

SELECT *
FROM TEmployees
WHERE Status = {code for active status}
  AND Name NOT LIKE '%[0-9]%'

在这种情况下,我认为在EF中使用SQL查询是最好的方法。请问你能否为我解释一下如何将上面的lambda表达式(在更新中)转换为EF中的SQL查询? - Jack

2
你可以使用 Regex.IsMatch
yourEnumerable.Where(m => !Regex.IsMatch(m.EmployeeName, @"\d"));

其实我之前也尝试使用!Regex,但那样的情况下没有记录返回。你有什么想法吗? - Jack
尝试使用这个模式 ^[0-9]*$ 代替。 - Bon Macalindong
谢谢,但没有检索到任何记录。有什么想法? - Jack
我模拟了这个过程,这个模式可以工作:@"\d"。我的测试数据是sss213, ggg, g1g, 1gg, xxx。它只返回了"ggg"和"xxx"。 - Bon Macalindong
我再次进行了测试,但是没有返回任何数据。您能否看一下上面显示的Update中的lambda表达式? - Jack

1
我能想到的使用Linq-To-Entities的唯一解决方案是定义一个字符串数组,然后查看您的字符串是否包含其中任何一个元素:
string[] digits = new { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
...Where(m => !digits.Any(m.EmployeeName.Contains(d));

我可以想象对于大型数据集,这将是一个较慢的查询,因此我会通过EF执行sql。

是的,我同意你的观点。因此,我认为在EF中使用SQL查询是最好的想法。你能否请说明一下如何将上面的Lambda表达式(在更新中)转换为EF中的SQL查询?谢谢... - Jack

1
尝试这个更多信息 link
return Json(db.TEmployees
.Where(m => m.Status == Enums.Status.Active && !m.EmployeeName.Any(char.IsDigit))
.Select(m => new { ID = m.EmployeeID, EmployeeName = m.EmployeeName }).ToList(), 
    JsonRequestBehavior.AllowGet);

编辑:在返回的JSON中添加ToList()


谢谢,我也看了那个页面但没用。有什么想法吗? - Jack
1
EF不支持表达式char.IsDigit - D Stanley
请添加AsEnumerable()方法并再次尝试一下,请检查我的编辑。@binary - Alper Tunga Arslan
1
请注意,这不会在 SQL 中执行筛选。它将返回数据库中的所有行,然后对它们进行筛选。 - Nathan Koop
抱歉,在那种情况下,它会针对NULL值抛出错误。我通过使用纯SQL查询解决了这个问题。谢谢,已投票+。 - Jack
显示剩余2条评论

1

没有通用的LINQ to Entities解决方案。

然而,如果你只针对Sql Server数据库,你可以使用SqlFunctions.PatIndex规范函数,像这样:

db.TEmployees
    .Where(m => m.Status == Enums.Status.Active &&
        SqlFunctions.PatIndex("%[0-9]%", m.EmployeeName) == 0)
//...

谢谢回复,但我也可以使用SQL查询来解决问题,而不使用lambda表达式。 已投票+ - Jack

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