![](/img/trans.png)
[英]Migrating DBFunctions from Entity Framework 6 to Entity framework Core
[英]Extending DbFunctions in Entity Framework Core?
使用 .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()
或ToListAsync()
的調用顯式切換到客戶端評估。 有關詳細信息,請參閱https://go.microsoft.com/fwlink/?linkid=2101038 。來源=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(ExpressionVisitorvisitor) 在 System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) 在 Microsoft.ExpressEntityQueryVisitorTranslationCore。 .VisitMethodCall(MethodCallExpression methodCallExpression) 在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) 在 System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitorvisitor) 在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) 在 System.Linq.Expressions.ExpressionVisitor.node .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 數據庫、表達式查詢、IModel 模型、布爾異步)在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_01.<Execute>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](對象 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.<Execute>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
1 編譯1 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() 在 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.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.Se archOperations.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)映射器、ObjectMethodExecutor 執行器、對象控制器、Object[] 參數)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
是否可以使用 Entity Framework Core 在應用程序中擴展 DbFunctions,並在 LINQ 中使用它? 如何?
評論:
String.Contains()
在 EF Core 查詢中區分大小寫,但在 SQL 中轉換為 LIKE 的 EF 中不區分大小寫。
您可以使用簡單的 one -> context.Users.Where(x => (conditions.Keyword == null || x.UserName.Contains(conditions.Keyword)))。 如果conditions.Keyword 為空,則跳過過濾器。
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,
};
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));
}
PS 問題的標題方式看起來接近什么標量函數映射,但它不適用於 LIKE 子句的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.