LINQ to entity — фильтрация данных с помощью IQueryable.Contains

Я боролся с проблемой в течение некоторого времени. В настоящее время я перемещаю старый проект из структуры сущностей в ядро ​​​​сущности 2.2.4.

В этом проекте пользователь может определить множество критериев поиска на веб-странице, прежде чем он сделает запрос данных на сервер. Я не вдаюсь в подробности запроса, но он связывает 5 таблиц, 2 из которых содержат список динамических параметров имя+значение (вертикально хранящихся в таблице). Эти параметры связаны с их родительской таблицей (объектом). Запрос возвращает список уникальных идентификаторов. Они представляют собой уникальный ключ к одной из родительских таблиц.

Для удобства и из-за сложности перевода такого запроса в запрос LINQ я решил сначала динамически построить запрос с критериями поиска в строке С#.

В предыдущей версии EntityFramework я достиг этого с помощью:

List<string> arrFilteredGlobalId = _dbContext.Database.SqlQuery<string>("select GLOBALID from.....").ToList<string>();

Тогда я могу сделать:

var full = from bundle in _dbContext.BUNDLE
                where arrFilteredGlobalId.Contains(bundle.GLOBALID)
                select bundle;
int num = full.Count(); // <= works perfectly

В свежей новой версии EntityFramework Core context.Database.SqlQuery больше не существует. Мне пришлось сделать следующее, чтобы добиться той же логики:

  1. Объявите новый класс DBGlobalIdentifier с одним свойством
public class DBGlobalIdentifier
{
    public string GLOBALID { get; set; }
}
  1. В моем классе контекста я объявил объект DbQuery, типизированный с ранее определенным классом DBGlobalIdentifier.
public virtual DbQuery<DBGlobalIdentifier> Identifiers { get; set; }
  1. Наконец, я делаю
IQueryable<DBGlobalIdentifier> arrFilteredGlobalId =  this._context.Identifiers.FromSql("select GLOBALID from.....");

// DBGlobalIdentifier test = arrFilteredGlobalId.First(); <== works perfectly.

var full = from bundle in _context.Bundles
                where arrFilteredGlobalId.Contains(new DBGlobalIdentifier() { GLOBALID = bundle.GLOBALID })
                select bundle;

int num = full.Count(); // <= it fails and returns an exception (see here under)

Возвращено исключение:

An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
Microsoft.EntityFrameworkCore.Query.Internal.QueryOptimizer.TryOptimizeContains(ResultOperatorBase resultOperator, QueryModel queryModel)

NullReferenceException: Object reference not set to an instance of an object.
Microsoft.EntityFrameworkCore.Query.Internal.QueryOptimizer.TryOptimizeContains(ResultOperatorBase resultOperator, QueryModel queryModel)
Microsoft.EntityFrameworkCore.Query.Internal.QueryOptimizer.VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index)
Remotion.Linq.Clauses.ResultOperatorBase.Accept(IQueryModelVisitor visitor, QueryModel queryModel, int index)
Remotion.Linq.QueryModelVisitorBase.VisitResultOperators(ObservableCollection<ResultOperatorBase> resultOperators, QueryModel queryModel)
Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.TransformingQueryModelExpressionVisitor<TVisitor>.VisitSubQuery(SubQueryExpression expression)
Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
Remotion.Linq.Clauses.WhereClause.TransformExpressions(Func<Expression, Expression> transformation)
Remotion.Linq.QueryModel.TransformExpressions(Func<Expression, Expression> transformation)
Microsoft.EntityFrameworkCore.Query.Internal.QueryOptimizer.Optimize(QueryCompilationContext queryCompilationContext, QueryModel queryModel)
Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.OptimizeQueryModel(QueryModel queryModel, bool asyncQuery)
Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.OptimizeQueryModel(QueryModel queryModel, bool asyncQuery)
Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor<TResult>(QueryModel queryModel)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore<TResult>(Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database, IDiagnosticsLogger<Query> logger, Type contextType)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass13_0<TResult>.<Execute>b__0()
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore<TFunc>(object cacheKey, Func<Func<QueryContext, TFunc>> compiler)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute<TResult>(Expression query)
System.Linq.Queryable.Count<TSource>(IQueryable<TSource> source)

Идея о моей проблеме?

Спасибо! Фред

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
0
975
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина проблемы не совсем интересна — стек вызовов исключений указывает на ошибку транслятора запросов EF Core (их еще много). Скорее всего, это вызвано (неожиданным) использованием new DBGlobalIdentifier внутри Contains.

Идея с типом запроса правильная. Поскольку select необработанные SQL-запросы — это компонуемый, решение состоит в том, чтобы извлечь значение обратно с помощью Select, а затем использовать обычный Contains:

var arrFilteredGlobalId = _context.Identifiers
    .FromSql("select GLOBALID from.....")
    .Select(x => x.GLOBALID); // <--

var full = from bundle in _context.Bundles
           where arrFilteredGlobalId.Contains(bundle.GLOBALID)
           select bundle;

Другие вопросы по теме