#c# #entity-framework-core #.net-6.0 #ef-core-6.0
Вопрос:
Я пытаюсь реализовать глобальный фильтр запросов для аренды в своем приложении. У меня AssessmentModels
может быть несколько владельцев, владельцы приходят от третьей стороны, которую я не полностью контролирую, но могу настроить по мере необходимости. (И может манипулировать, прежде чем я сохраню в своей базе данных) Прямо сейчас Owners
они хранятся в виде строки, разделенной точкой с запятой (например, team1;team2
).
Я придумал следующее, которое работает для выбора данных, но не работает для глобального фильтра запросов:
private Expressionlt;Funclt;AssessmentModel, boolgt;gt; GetAssessmentFilter() { // The lambda parameter. var assessmentParameter = Expression.Parameter(typeof(AssessmentModel), "a"); // Build the individual conditions to check against. var orConditions = _adminTeamNames .Select(keyword =gt; (Expressionlt;Funclt;AssessmentModel, boolgt;gt;)(a =gt; EF.Functions.Like(a.Owners, $"%{keyword}%"))) .Select(lambda =gt; (Expression)Expression.Invoke(lambda, assessmentParameter)) .ToList(); // Combine the individual conditions to an expression tree of nested ORs. var orExpressionTree = orConditions .Skip(1) .Aggregate( orConditions.First(), (current, expression) =gt; Expression.OrElse(expression, current)); // Build the final predicate (a lambda expression), so we can use it inside of `.Where()`. var predicateExpression = (Expressionlt;Funclt;AssessmentModel, boolgt;gt;)Expression.Lambda( orExpressionTree, assessmentParameter); return predicateExpression; }
Так, var result = db.Assessments.Where(predicateExpression).ToList();
работает, но modelBuilder.Entitylt;AssessmentModelgt;().HasQueryFilter(predicateExpression);
выдает ошибку:
System.InvalidOperationException : The LINQ expression 'DbSetlt;AssessmentModelgt;() .Where(a =gt; Invoke(a =gt; value(DbFunctions).Like(a.Owners, "%Los%"), a) || Invoke(a =gt; value(DbFunctions).Like(a.Owners, "%Atl%"), a) )' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Ответ №1:
Ядро AFAIK EF не очень хорошо переводит выражения вызова. Попробуйте вручную заменить параметр построения лямбды вашим пользовательским выражением параметра (т. е. assessmentParameter
) :
var orConditions = _adminTeamNames .Select(keyword =gt; (Expressionlt;Funclt;AssessmentModel, boolgt;gt;)(a =gt; EF.Functions.Like(a.Owners, $"%{keyword}%"))) .Select(lambda =gt; new ReplacingExpressionVisitor(lambda.Parameters, new []{assessmentParameter}).Visit(lambda.Body)) .ToList();
Комментарии:
1. Вот и все-спасибо!