有了.NET Core 3.1.1和Entity Framework Core 3.1.1,我有了:
var query = from user in context.Users
join userRole in userRoleView on user.Id equals userRole.UserId into gj
from p in gj.DefaultIfEmpty()
select new
{
user.Id,
user.UserName,
RoleName = p.Rolename,
user.CreatedUtc,
user.ModifiedUtc,
};
if (!String.IsNullOrWhiteSpace(conditions.Keyword))
{
query = query.Where(d => EF.Functions.Like(d.UserName, "%" + conditions.Keyword + "%"));
}
这很好,然后我想拥有EF.Functions.Contains(d.UserName, conditions.Keyword)
,所以我写了一个扩展名:
public static class DbFunctionsExtensions
{
public static bool Contains(this DbFunctions _, string matchExpression, string keyword)
{
return _.Like(matchExpression, "%" + keyword + "%");
}
}
但是,在运行时
query.Where(d => EF.Functions.Contains(d.UserName, conditions.Keyword))
我收到此异常:
System.InvalidOperationException ...无法翻译。
以一种可以翻译的形式重写查询,或者通过插入对
AsEnumerable()
,AsAsyncEnumerable()
,ToList()
或{{1}的调用来显式切换到客户端评估}。有关更多信息,请参见https://go.microsoft.com/fwlink/?linkid=2101038。Source = Microsoft.EntityFrameworkCore
StackTrace: 在Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.g__CheckTranslated | 8_0(ShapedQueryExpression翻译,<> c__DisplayClass8_0&)
在Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
在Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
在System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor访问者)处
在System.Linq.Expressions.ExpressionVisitor.Visit(表达式节点)上
在Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
在Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) 在System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor访问者) 在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点) 在Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) 在Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) 在System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor访问者) 在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点) 在Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor [TResult](表达式查询) 在Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery [TResult](表达式查询,布尔异步) 在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore [TResult](IDatabase数据库,表达式查询,IModel模型,布尔异步) 在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler。<> c__DisplayClass9_0ToListAsync()
1编译器处) 在Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery [TResult](对象cacheKey,Func1.<Execute>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
1.GetEnumerator() 在System.Collections.Generic.LargeArrayBuilder1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1个项目中) 在System.Collections.Generic.EnumerableHelpers.ToArray [T](IEnumerable1.AddRange(IEnumerable
1源)处 在C:\ VSProjects \ ApsCloudTrunk \ APS.WebPos.DALCore \ SearchOperations.cs:line 96中的APS.WebPos.DAL.SearchOperations.GetActivePeopleByKeyword(String关键字) 在C:\ VSProjects \ ApsCloudTrunk \ APS.WebPos.WebApiCore \ Controllers \ SearchController.cs:第25行的APS.WebPos.WebApi.Controllers.SearchController.GetActivePeopleByKeyword(String关键字)处 在Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target,Object []参数) 在Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper映射器,ObjectMethodExecutor执行器,对象控制器,Object []参数) 在Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() 在Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(状态和下一个,范围和范围,对象和状态,布尔值和isCompleted)处 在Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
是否可以在具有Entity Framework Core的应用程序中扩展DbFunction,并在LINQ中使用它?怎么样?
备注:
1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable
在EF Core查询中区分大小写,尽管在将EF转换为SQL的LIKE中不区分大小写。
答案 0 :(得分:0)
您可以使用简单的一个-> context.Users.Where(x =>(conditions.Keyword == null || x.UserName.Contains(conditions.Keyword)))。如果condition.Keyword为null,则跳过过滤器。
var query = from user in context.Users.Where(x => (conditions.Keyword == null || x.UserName.Contains(conditions.Keyword)))
join userRole in userRoleView
on user.Id equals userRole.UserId into gj
from p in gj.DefaultIfEmpty()
select new
{
user.Id,
user.UserName,
RoleName = p.Rolename,
user.CreatedUtc,
user.ModifiedUtc,
};
答案 1 :(得分:0)
Where
方法的参数是Expression
,在将查询转换为SQL时,它的主体无关紧要。这就是为什么您遇到例外。
要使其正常工作,您需要动态构建一个表达式。
public static Expression<Func<T, bool>> Like<T>(Expression<Func<T, string>> prop, string keyword)
{
var concatMethod = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) });
return Expression.Lambda<Func<T, bool>>(
Expression.Call(
typeof(DbFunctionsExtensions),
nameof(DbFunctionsExtensions.Like),
null,
Expression.Constant(EF.Functions),
prop.Body,
Expression.Add(
Expression.Add(
Expression.Constant("%"),
Expression.Constant(keyword),
concatMethod),
Expression.Constant("%"),
concatMethod)),
prop.Parameters);
}
然后在查询中使用它
if (!String.IsNullOrWhiteSpace(conditions.Keyword))
{
query = query.Where(Like<User>(d => d.UserName, conditions.Keyword));
}
P.S。问题的标题方式看起来与Scalar function mapping相似,但不适用于LIKE子句。