Проверьте, содержит ли значение String любое число, используя выражение Lambda

У меня есть запрос SQL, который извлекает только имена, не содержащие никакого числа:

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

С другой стороны, при попытке использовать этот запрос в Lambda Expression с различными комбинациями, как показано ниже, ни один из них не работает:

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

или

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

Как использовать метод NOT LIKE в Lambda Expression?

Обновление: Мое выражение лямбда показано ниже:

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);

Ответ 1

Насколько я знаю, вы не можете применять регулярное выражение в Linq к 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

Ответ 2

Попробуйте эту дополнительную информацию ссылка:

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);

EDIT: Добавить ToList() в ответ json

Ответ 3

EF ограничен возможностью генерировать точный SQL, который вы хотите. Я не знаю конкретного выражения, которое будет генерировать шаблон [0-9] в вашем предложении LIKE.

Список Строковые функции  которые поддерживаются EF, документируются в MSDN. Ни один из них не может быть использован для определения того, содержит ли строка произвольную цифру или нет.

Некоторые другие варианты:

  • Используйте точный SQL, который вы хотите на С#, и вызовите ExecuteStoreCommand
  • Возвращайте больше объектов, чем вам нужно из БД и фильтруйте в памяти, используя AsEnumerable()

Эквивалентный SQL будет чем-то вроде

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

Ответ 4

Вы можете использовать Regex.IsMatch.

yourEnumerable.Where(m => !Regex.IsMatch(m.EmployeeName, @"\d"));

Ответ 5

Единственное решение, использующее Linq-To-Entities, о котором я могу думать, это определить строковый массив и посмотреть, содержит ли ваша строка ни одно из них:

string[] digits = new { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
...Where(m => !digits.Any(m.EmployeeName.Contains(d));

Я могу представить, что это будет медленный запрос, хотя для больших наборов данных, поэтому я бы просто выполнил sql через EF.

Ответ 6

Нет общего решения LINQ to Entities.

Однако если вы нацеливаете базу данных Sql только, вы можете использовать SqlFunctions.PatIndex каноническую функцию следующим образом:

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