Я не знаю, как заставить Entity Framework использовать «настоящий» оператор LIKE, но возможный обходной путь - это выражение LIKE в выражениях StartsWith
, Contains
и EndsWith
Например:
LIKE 'a%' => StartsWith("a")
LIKE '%a' => EndsWith("a")
LIKE '%a%' => Contains("a")
LIKE 'a%b' => StartsWith("a") && EndsWith("b")
LIKE 'a%b%' => StartsWith("a") && Contains("b")
И так далее ...
Обратите внимание, что это не совсем эквивалентно использованию LIKE в SQL: например, LIKE '%abc%bcd%'
приведет к Contains("abc") && Contains("bcd")
. Это будет соответствовать "abcd", даже если исходное условие LIKE не будет. Но в большинстве случаев этого должно быть достаточно.
Вот пример реализации, использующий PredicateBuilder
и LinqKit для построения выражений на основе шаблона LIKE:
public static class ExpressionHelper
{
public static Expression<Func<T, bool>> StringLike<T>(Expression<Func<T, string>> selector, string pattern)
{
var predicate = PredicateBuilder.True<T>();
var parts = pattern.Split('%');
if (parts.Length == 1) // not '%' sign
{
predicate = predicate.And(s => selector.Compile()(s) == pattern);
}
else
{
for (int i = 0; i < parts.Length; i++)
{
string p = parts[i];
if (p.Length > 0)
{
if (i == 0)
{
predicate = predicate.And(s => selector.Compile()(s).StartsWith(p));
}
else if (i == parts.Length - 1)
{
predicate = predicate.And(s => selector.Compile()(s).EndsWith(p));
}
else
{
predicate = predicate.And(s => selector.Compile()(s).Contains(p));
}
}
}
}
return predicate;
}
}
А вот как вы можете его использовать:
var expr = ExpressionHelper.StringLike<YourClass>(x => x.Type, typeFilter);
query = query.AsExpandable().Where(expr.Compile());
Я только что попробовал это с простой моделью EF, и, кажется, работает нормально :) 1026 *