I\'m using LINQ 2 Entities. Following is the problem:
string str = \'%test%.doc%\'
.Contains(str) // converts this into LIKE \'%~%test~%.doc~%%\'
Following on from Magnus' correct answer, here is an extension method that can be re-used, as I needed in my project.
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;
}
}
Usage:
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();
The extension makes use of the predicate builder at http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/. The resulting sql does a single table scan of the table, no matter how many terms are in there. Jo Vdb has an example you could start from if you wanted an extension of iQueryable instead.