c# - 解决 "InvalidOperationException: The LINQ expression [...] could not be translated"并保留 ToListAsync()

标签 c# asp.net linq asp.net-core ef-core-3.0

在 EF Core 3.x 中,客户端不再评估无法转换的 LINQ 查询。据我了解,这意味着它无法处理无法直接转换为 SQL 的代码。


就我而言,我想使用 foreach(PropertyInfo in type.GetProperties()) 来评估类的每个组件。

private static bool stringInMovement(Movement m, string toTest)
{
    foreach(PropertyInfo component in typeof(Movement).GetProperties())
    {
        try {
            if (component.GetValue(m).ToString().ToLower().Contains(toTest.ToLower()))
                return true;
        }
        catch { }

    }
    return false;
}

然后在 where 语句中使用它:

movements = movements.Where(m=> stringInMovement(m, SearchString));

我想将结果保留为 IQueryable,因为在它所在的函数之后是一个异步任务,最后一行是

Movements = await movements.AsNoTracking().ToListAsync();

我希望将所有函数保持为异步,并且我不想使用 10x m.Component.Contains(searchstring) 编写 where 语句。顺便搜索数据库的特定元素。

感谢您的帮助!

尝试搜索某些内容时遇到的错误:

    Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|8_0(ShapedQueryExpression translated, ref <>c__DisplayClass8_0 )
    Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
    Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
    System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
    System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
    Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor<TResult>(Expression query)
    Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery<TResult>(Expression query, bool async)
    Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore<TResult>(IDatabase database, Expression query, IModel model, bool async)
    Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass12_0<TResult>.<ExecuteAsync>b__0()
    Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore<TFunc>(object cacheKey, Func<Func<QueryContext, TFunc>> compiler)
    Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery<TResult>(object cacheKey, Func<Func<QueryContext, TResult>> compiler)
    Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
    Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
    Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<TResult>.GetAsyncEnumerator(CancellationToken cancellationToken)
    System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<T>.GetAsyncEnumerator()
    Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync<TSource>(IQueryable<TSource> source, CancellationToken cancellationToken)
    Intuo.IndexModel.OnGetAsync() in Index.cshtml.cs
    +
                Movements = await movements.AsNoTracking().ToListAsync();
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+NonGenericTaskHandlerMethod.Execute(object receiver, object[] arguments)
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
    Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
    Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

最佳答案

你想要的是动态生成一个Expression<Lambda>在 where 子句中使用。

        public static Expression<Func<T,bool>> ContainsString<T>(string value)
        {
            var constValue = Expression.Constant(value);
            var parameter = Expression.Parameter(typeof(T), "p");

            return Expression.Lambda<Func<T, bool>>(
                typeof(T).GetProperties()
                    .Where(p => p.PropertyType == typeof(string))
                    .Select(p => (Expression)Expression.Call(
                        Expression.Property(parameter, p), 
                        "Contains", 
                        new Type[] { typeof(string) },
                        constValue))
                    .Aggregate((a, c) => Expression.OrElse(a, c)),
                parameter);
        }

        movements = movements.Where(ContainsString<Movement>(SearchString));

关于c# - 解决 "InvalidOperationException: The LINQ expression [...] could not be translated"并保留 ToListAsync(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59852208/

相关文章:

c# - 如何减少gridview列asp.net C#中的小数位

ASP.net 多数据库链接

c# - 获取最大元素的索引

asp.net - LINQ to SQL - 字段包含在已知字符串中

c# - 编辑/修改 C# 应用程序设置

c# - 无法向窗体添加控件

c# - 带有自定义事件的天蓝色数据工厂项目

c# - 无法更新用户,因为它正在检查唯一的用户名

c# - 如何在 C# 中声明枚举列表<>

c# - 读取文件时拆分字符串并忽略一个字符串 LINQ