为 EfCore 构建谓词 IQueryable.Where<T>
Build predicate for EfCore IQueryable.Where<T>
我想为 IQueryable 创建一个 Search<T>
扩展方法,但是遇到了一个无法翻译的 LINQ 表达式运行时错误。
public static IQueryable<T> Search<T>(this IQueryable<T> source, Func<T, string> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
return source.Where(x => EF.Functions.Like(expression(x), $"%{search}%"));
}
用法:
dbContext.People.Search(x => x.Name, "Joe").ToList();
我猜错误的行是expression(x)
,但正确的方法是什么?
它不使用 Like 功能,但作为扩展可以正常工作。
var result = dbContex.Currencies.Search(x=>x.Symbol, "EUR").ToList();
public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T,string>> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var value = Expression.Constant(search, typeof(string));
var exp1 = Expression.Call(expression.Body, method, value);
var ex2 = Expression.Lambda<Func<T, bool>>(exp1, expression.Parameters[0]);
return source.Where(ex2);
}
这是一个经过测试且有效的解决方案。
public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
var property = typeof(T).GetProperty(((MemberExpression)expression.Body).Member.Name);
var parameter = Expression.Parameter(typeof(T));
var functions = Expression.Property(null, typeof(EF).GetProperty(nameof(EF.Functions)));
var like = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like),
new[] { functions.Type, typeof(string), typeof(string) });
Expression expressionProperty = Expression.Property(parameter, property.Name);
var body = Expression.Call(null, like, functions, expressionProperty, Expression.Constant($"%{search}%"));
return source.Where(Expression.Lambda<Func<T, bool>>(body, parameter));
}
我想为 IQueryable 创建一个 Search<T>
扩展方法,但是遇到了一个无法翻译的 LINQ 表达式运行时错误。
public static IQueryable<T> Search<T>(this IQueryable<T> source, Func<T, string> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
return source.Where(x => EF.Functions.Like(expression(x), $"%{search}%"));
}
用法:
dbContext.People.Search(x => x.Name, "Joe").ToList();
我猜错误的行是expression(x)
,但正确的方法是什么?
它不使用 Like 功能,但作为扩展可以正常工作。
var result = dbContex.Currencies.Search(x=>x.Symbol, "EUR").ToList();
public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T,string>> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var value = Expression.Constant(search, typeof(string));
var exp1 = Expression.Call(expression.Body, method, value);
var ex2 = Expression.Lambda<Func<T, bool>>(exp1, expression.Parameters[0]);
return source.Where(ex2);
}
这是一个经过测试且有效的解决方案。
public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> expression, string search)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrWhiteSpace(search))
return source;
var property = typeof(T).GetProperty(((MemberExpression)expression.Body).Member.Name);
var parameter = Expression.Parameter(typeof(T));
var functions = Expression.Property(null, typeof(EF).GetProperty(nameof(EF.Functions)));
var like = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like),
new[] { functions.Type, typeof(string), typeof(string) });
Expression expressionProperty = Expression.Property(parameter, property.Name);
var body = Expression.Call(null, like, functions, expressionProperty, Expression.Constant($"%{search}%"));
return source.Where(Expression.Lambda<Func<T, bool>>(body, parameter));
}