Оператор LIKE в LINQ

Есть ли способ сравнить строки в выражении C # LINQ, аналогичном оператору LIKE SQL?

Предположим, у меня есть список строк. В этом списке я хочу найти строку. В SQL я мог бы написать:

 SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%' 

Вместо вышесказанного запрос требует синтаксиса linq.

 using System.Text.RegularExpressions; … var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase); var sPortCode = Database.DischargePorts .Where(p => regex.IsMatch(p.PortName)) .Single().PortCode; 

Мой синтаксис LINQ не работает. Что у меня получилось?

Обычно вы используете String.StartsWith / EndsWith / Contains . Например:

 var portCode = Database.DischargePorts .Where(p => p.PortName.Contains("BALTIMORE")) .Single() .PortCode; 

Я не знаю, есть ли способ делать правильные регулярные выражения с помощью LINQ to SQL. (Обратите внимание, что это действительно зависит от того, какой провайдер вы используете – в LINQ to Objects было бы хорошо, это вопрос, может ли провайдер преобразовать вызов в свой собственный формат запроса, например SQL.)

EDIT: Как говорит BitKFu, Single должен использоваться, когда вы ожидаете ровно один результат – когда это ошибка, если это не так. В зависимости от того , что ожидается, следует использовать опции SingleOrDefault , FirstOrDefault или First .

Regex? нет. Но для этого запроса вы можете просто использовать:

  string filter = "BALTIMORE"; (blah) .Where(row => row.PortName.Contains(filter)) (blah) 

Если вы действительно хотите SQL LIKE , вы можете использовать System.Data.Linq.SqlClient.SqlMethods.Like(...) , который LINQ-to-SQL отображает LIKE в SQL Server.

Как уже упоминал Джон Скит и Марк Гравелл, вы можете просто принять условие наличия. Но в случае вашего подобного запроса очень опасно принимать оператор Single (), потому что это означает, что вы найдете только 1 результат. В случае большего количества результатов вы получите прекрасное исключение 🙂

Поэтому я предпочел бы использовать FirstOrDefault () вместо Single ():

 var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE")); var portcode = first != null ? first.PortCode : string.Empty; 

Ну … иногда может быть неудобно использовать Contains , StartsWith или EndsWith особенно, когда поиск значения определяет LIKE statment, например, переданное ‘value%’ требует от разработчика использовать функцию StartsWith в выражении. Поэтому я решил написать расширение для объектов IQueryable .

Применение

 // numbers: 11-000-00, 00-111-00, 00-000-11 var data1 = parts.Like(p => p.Number, "%11%"); // result: 11-000-00, 00-111-00, 00-000-11 var data2 = parts.Like(p => p.Number, "11%"); // result: 11-000-00 var data3 = parts.Like(p => p.Number, "%11"); // result: 00-000-11 

Код

 public static class LinqEx { private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains"); private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); public static Expression> LikeExpression(Expression> property, string value) { var param = Expression.Parameter(typeof(TSource), "t"); var propertyInfo = GetPropertyInfo(property); var member = Expression.Property(param, propertyInfo.Name); var startWith = value.StartsWith("%"); var endsWith = value.EndsWith("%"); if (startWith) value = value.Remove(0, 1); if (endsWith) value = value.Remove(value.Length - 1, 1); var constant = Expression.Constant(value); Expression exp; if (endsWith && startWith) { exp = Expression.Call(member, ContainsMethod, constant); } else if (startWith) { exp = Expression.Call(member, EndsWithMethod, constant); } else if (endsWith) { exp = Expression.Call(member, StartsWithMethod, constant); } else { exp = Expression.Equal(member, constant); } return Expression.Lambda>(exp, param); } public static IQueryable Like(this IQueryable source, Expression> parameter, string value) { return source.Where(LikeExpression(parameter, value)); } private static PropertyInfo GetPropertyInfo(Expression expression) { var lambda = expression as LambdaExpression; if (lambda == null) throw new ArgumentNullException("expression"); MemberExpression memberExpr = null; switch (lambda.Body.NodeType) { case ExpressionType.Convert: memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression; break; case ExpressionType.MemberAccess: memberExpr = lambda.Body as MemberExpression; break; } if (memberExpr == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); var output = memberExpr.Member as PropertyInfo; if (output == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); return output; } } 

В родной LINQ вы можете использовать комбинацию Contains/StartsWith/EndsWith или RegExp.

В методе LINQ2SQL используется метод SqlMethods.Like()

  from i in db.myTable where SqlMethods.Like(i.field, "tra%ata") select i 

Добавьте Assembly: System.Data.Linq (в System.Data.Linq.dll), чтобы использовать эту функцию.

Проще, как это

 string[] users = new string[] {"Paul","Steve","Annick","Yannick"}; var result = from u in users where u.Contains("nn") select u; 

Результат -> Антик, Янник

Вы можете вызвать один метод с помощью предиката:

 var portCode = Database.DischargePorts .Single(p => p.PortName.Contains("BALTIMORE")) .PortCode; 
  .Where(e => e.Value.StartsWith("BALTIMORE")) 

Это работает как «LIKE» SQL …

В идеале вы должны использовать StartWith или EndWith .

Вот пример:

 DataContext dc = new DCGeneral(); List lstPerson= dc.GetTable().StartWith(c=> c.strNombre).ToList(); return lstPerson; 
  public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } } var portCode = Database.DischargePorts .Single(p => p.PortName.Contains( new string[] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) )) .PortCode; 

Просто добавьте методы расширения объектов строки.

 public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } } 

Применение:

 use namespase that contains this class; var sPortCode = Database.DischargePorts .Where(p => p.PortName.Contains(new string [] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) ) .Single().PortCode; 

Я нашел решение для имитации оператора SQL LIKE. См. Ответ, который я пишу здесь. https://stackoverflow.com/a/46592475/1186073

  • mysql как повышение производительности
  • Давайте будем гением компьютера.