LINQ中的LIKE运算符

有什么办法来比较类似于SQL的LIKE运算符的C#LINQexpression式中的string吗?

假设我有一个string列表。 在这个列表中,我想search一个string。 在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做适当的正则expression式。 (请注意,它确实取决于你使用的是哪一个提供者 – 在LINQ to Objects中应该没有问题;提供者是否可以将调用转换为原生查询格式,例如SQL。

编辑:正如BitKFu所说的,当你期望得到一个结果的时候,应该使用Single 。如果不是这样的话,那么这个结果是错误的。 SingleOrDefaultFirstOrDefaultFirst选项应该使用,具体取决于期望的。

正则expression式? 没有。 但是对于那个查询,你可以使用:

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

如果你真的想要SQL LIKE ,你可以使用System.Data.Linq.SqlClient.SqlMethods.Like(...) ,LINQ到SQL映射到SQL Server中的LIKE

正如Jon Skeet和Marc Gravell已经提到的那样,你可以简单地采取包含条件。 但是如果你喜欢查询,使用Single()语句是非常危险的,因为这意味着你只能find1个结果。 如果有更多的结果,你会收到一个很好的例外:)

所以我宁愿使用FirstOrDefault()而不是Single():

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

在本机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中)以使用此function。

那么…有时使用ContainsStartsWithEndsWith可能会感到不舒服,尤其是在search值时确定LIKE语句,例如传递'value%'要求开发人员在expression式中使用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<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> 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<Func<TSource, bool>>(exp, param); } public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> 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; } } 
  .Where(e => e.Value.StartsWith("BALTIMORE")) 

这工作像SQL的“LIKE”…

这是一个简单的

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

结果 – > Annick,Yannick

您可以使用谓词调用单个方法:

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

理想情况下,你应该使用StartWithEndWith

这里是一个例子:

 DataContext dc = new DCGeneral(); List<Person> lstPerson= dc.GetTable<Person>().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; 

只需添加到string对象扩展方法。

 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; 

我find了一个模仿SQL LIKE运算符的解决scheme。 请参阅我在这里写的答案https://stackoverflow.com/a/46592475/1186073