无法翻译带有LinqKit的表达式-EF Core



我真的想知道是否有人能帮我。我们有一种非常通用的方法来使用LinqKit构建表达式。使用内部Lists,一切都很好,但在使用EF Core时,我们遇到了一些错误。

System.InvalidOperationException: The LINQ expression 'DbSet<Entity>()
.Where(k => False || __propertyInfo_0.GetValue(k) != null && __propertyInfo_0.GetValue(k).ToString().Contains(__GenericTableOptions_BaseQueryParameters_Search_1) && True)' could not be translated. 

以可翻译的形式重写查询,或者通过插入对"AsEnumerable"、"AsAsyncEnumerable("、"ToList"或"ToListAsync"的调用,显式切换到客户端评估。看见https://go.microsoft.com/fwlink/?linkid=2101038了解更多信息。

通用表达式生成器看起来像这个

private Expression<Func<TEntity, bool>> BuildGenericSearchExpression()
{
Expression<Func<TEntity, bool>> expression = x => false;
var searchFields = GenericTableOptions.SearchColumns;
var propertyInfos = GetColumnsAsProperties(typeof(TEntity), searchFields).ToList();
if (propertyInfos.Count == 0)
{
// Returning true to allow AND chaining of multiple conditions
return x => true;
}
foreach (var propertyInfo in propertyInfos)
{
expression = expression.Or(x =>
propertyInfo.GetValue(x) != null &&
propertyInfo.GetValue(x)!.ToString()!.Contains(GenericTableOptions.BaseQueryParameters.Search));
}
return expression;
}

有人想解决这个问题吗?

此处不能使用expression.Or(...),必须动态构建LamdaExpression。

以下是更正后的代码,还删除了Null检查,SQL翻译不需要它。

private Expression<Func<TEntity, bool>> BuildGenericSearchExpression()
{
var searchFields = GenericTableOptions.SearchColumns;
var propertyInfos = GetColumnsAsProperties(typeof(TEntity), searchFields).ToList();
if (propertyInfos.Count == 0)
{
// Returning true to allow AND chaining of multiple conditions
return x => true;
}
Expression? predicate = null;
var param = Expression.Parameter(typeof(TEntity), "e");
var searchExpr = Expression.Constant(GenericTableOptions.BaseQueryParameters.Search);
foreach (var propertyInfo in propertyInfos)
{
var memberAccess = EnsureString(Expression.MakeMemberAccess(param, propertyInfo));
var condition = Expression.Call(memberAccess, nameof(string.Contains), Type.EmptyTypes, searchExpr);
predicate = predicate == null ? condition : Expression.OrElse(predicate, condition);
}
var predicateLambda = Expression.Lambda<Func<TEntity, bool>>(predicate!, param);
return predicateLambda;
}
// Helper method
private static Expression EnsureString(Expression expression)
{
if (expression.Type == typeof(string))
return expression;
if (expression.Type != typeof(object))
expression = Expression.Convert(expression, typeof(object));
expression = Expression.Call(_toStringMethod, expression);
return expression;
}
private static MethodInfo _toStringMethod = typeof(Convert).GetMethods()
.Single(m =>
m.Name == nameof(Convert.ToString) && m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == typeof(object)
);

最新更新