With .NET Core 3.1.1 and Entity Framework Core 3.1.1, I have:
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 + "%"));
}
This is working well, and then I would like to have EF.Functions.Contains(d.UserName, conditions.Keyword)
, so I wrote an extension:
public static class DbFunctionsExtensions
{
public static bool Contains(this DbFunctions _, string matchExpression, string keyword)
{
return _.Like(matchExpression, "%" + keyword + "%");
}
}
However, when running
query.Where(d => EF.Functions.Contains(d.UserName, conditions.Keyword))
I get this exception:
System.InvalidOperationException ... could not be translated.
Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either
AsEnumerable()
,AsAsyncEnumerable()
,ToList()
, orToListAsync()
. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.Source=Microsoft.EntityFrameworkCore
StackTrace: at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.g__CheckTranslated|8_0(ShapedQueryExpression translated, <>c__DisplayClass8_0& )
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query) at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_01.<Execute>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1 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.GetEnumerator() at System.Collections.Generic.LargeArrayBuilder1.AddRange(IEnumerable
1 items) at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source) at APS.WebPos.DAL.SearchOperations.GetActivePeopleByKeyword(String keyword) in C:\VSProjects\ApsCloudTrunk\APS.WebPos.DALCore\SearchOperations.cs:line 96 at APS.WebPos.WebApi.Controllers.SearchController.GetActivePeopleByKeyword(String keyword) in C:\VSProjects\ApsCloudTrunk\APS.WebPos.WebApiCore\Controllers\SearchController.cs:line 25 at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
Is it possible to extend DbFunctions in application with Entity Framework Core, and use it in LINQ? How?
Remarks:
String.Contains()
is case sensitive in EF Core query, though it is case insensitive in EF being translated into LIKE in SQL.
Contains
? - devNullquery.Where(d => EF.Functions.Contains(d.UserName, conditions.Keyword))
- ZZZDbFunctionsExtensions.Contains(EF.Functions, d.UserName, conditions.Keyword)
) - devNull