像LINQ to Entities中的运算符或使用通配符一样

我正在使用LINQ 2实体。 以下是问题:

string str = '%test%.doc%' .Contains(str) // converts this into LIKE '%~%test~%.doc~%%' 

预期转换:LIKE’%test%.doc%’

如果它是LINQ 2 SQL,我可以使用SqlMethods.Like,因为有人在我之前的问题中回答了它。 但是现在因为我使用L2E而不是L2S,我需要其他解决方案。

您可以尝试使用本文 ,其中作者描述了如何在LINQ to Entities中使用通配符构建LIKE语句。

编辑:由于原始链接现已死亡,这里是原始扩展类(根据评论中的Jon Koeter )和用法示例。

延期:

 public static class LinqHelper { //Support IQueryable (Linq to Entities) public static IQueryable WhereLike(this IQueryable source, Expression> valueSelector, string value, char wildcard) { return source.Where(BuildLikeExpression(valueSelector, value, wildcard)); } //Support IEnumerable (Linq to objects) public static IEnumerable WhereLike(this IEnumerable sequence, Func expression, string value, char wildcard) { var regEx = WildcardToRegex(value, wildcard); //Prevent multiple enumeration: var arraySequence = sequence as TSource[] ?? sequence.ToArray(); try { return arraySequence.Where(item => Regex.IsMatch(expression(item), regEx)); } catch (ArgumentNullException) { return arraySequence; } } //Used for the IEnumerable support private static string WildcardToRegex(string value, char wildcard) { return "(?i:^" + Regex.Escape(value).Replace("\\" + wildcard, "." + wildcard) + "$)"; } //Used for the IQueryable support private static Expression> BuildLikeExpression(Expression> valueSelector, string value, char wildcard) { if (valueSelector == null) throw new ArgumentNullException("valueSelector"); var method = GetLikeMethod(value, wildcard); value = value.Trim(wildcard); var body = Expression.Call(valueSelector.Body, method, Expression.Constant(value)); var parameter = valueSelector.Parameters.Single(); return Expression.Lambda>(body, parameter); } private static MethodInfo GetLikeMethod(string value, char wildcard) { var methodName = "Equals"; var textLength = value.Length; value = value.TrimEnd(wildcard); if (textLength > value.Length) { methodName = "StartsWith"; textLength = value.Length; } value = value.TrimStart(wildcard); if (textLength > value.Length) { methodName = (methodName == "StartsWith") ? "Contains" : "EndsWith"; } var stringType = typeof(string); return stringType.GetMethod(methodName, new[] { stringType }); } } 

用法示例:

 string strEmailToFind = "%@yahoo.com" IQueryable myUsers = entities.Users.WhereLike(u => u.EmailAddress, strEmailToFind, '%'); 

或者,如果您希望您的用户更习惯使用Windows资源管理器风格的通配符:

 string strEmailToFind = "*@yahoo.com" IQueryable myUsers = entities.Users.WhereLike(u => u.EmailAddress, strEmailToFind, '*'); 

SQL方法PATINDEX提供与LIKE相同的function。 因此,您可以使用SqlFunctions.PatIndex方法:

 .Where(x => SqlFunctions.PatIndex("%test%.doc%", x.MySearchField) > 0) 

继Magnus的正确答案后,这是一个可以重复使用的扩展方法,正如我在项目中所需要的那样。

 public static class LinqExtensions { public static Expression> WildCardWhere(this Expression> source, Expression> selector, string terms, char separator) { if (terms == null || selector == null) return source; foreach (string term in terms.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries)) { string current = term; source = source.And( Expression.Lambda>( Expression.Call(selector.Body, "Contains", null, Expression.Constant(current)), selector.Parameters[0] ) ); } return source; } } 

用法:

 var terms = "%test%.doc%"; Expression> whereClause = d => d; whereClause = whereClause.WildCardWhere(d => d.docName, terms, '%'); whereClause = whereClause.WildCardWhere(d => d.someOtherProperty, "another%string%of%terms", '%'); var result = ListOfDocs.Where(whereClause).ToList(); 

该扩展使用了http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/上的谓词构建器。 生成的sql对表执行单个表扫描,无论其中有多少个术语。 如果你想要iQueryable的扩展,你可以从Jo Vdb开始。

使用正则表达式……

以下将打印出当前目录中与test .doc *匹配的所有文件(dos通配符样式 – 我相信这是你要求的)

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.IO; namespace RegexFileTester { class Program { static void Main(string[] args) { string[] _files = Directory.GetFiles("."); var _fileMatches = from i in _files where Regex.IsMatch(i, ".*test*.doc.*") //where Regex.IsMatch(i, ".*cs") select i; foreach(var _file in _fileMatches) { Console.WriteLine(_file); } } } } 

拆分字符串

 var str = "%test%.doc%"; var arr = str.Split(new[]{'%'} ,StringSplitOptions.RemoveEmptyEntries); var q = tblUsers.Select (u => u); foreach (var item in arr) { var localItem = item; q = q.Where (x => x.userName.Contains(localItem)); } 

所以我尝试了同样的事情 – 尝试配对List以返回匹配SearchTerm的所有候选者。 我想要它,以便如果用户键入“亚利桑那州”它将返回所有内容,无论亚利桑那州的情况。 此外,如果用户键入“Arizona Cha”,它将返回“Arizona License Change”之类的项目。 以下工作:

 private List GetCertListBySearchString() { string[] searchTerms = SearchString.Split(' '); List allCerts = _context.Certifications.ToList(); allCerts = searchTerms.Aggregate(allCerts, (current, thisSearchString) => (from ac in current where ac.Name.ToUpper().Contains(thisSearchString.ToUpper()) select ac).ToList()); return allCerts; }