EF Core 3.1 - как сделать фильтрацию по параметрам? - PullRequest
0 голосов
/ 13 января 2020

В ef core 2.2 я мог бы сделать следующее:

        var query = _dbContext.BusinessUnits
            .Include(a => a.Parent)
            .Include(a => a.Region)
            .AsNoTracking().Select(x => new BUViewModel(x));
        if (!string.IsNullOrWhiteSpace(dto.Name))
        {
            query = query.Where(x => x.Name.ToLower().Contains(dto.Name.ToLower()));
        }

        if (dto.Level != null)
        {
            query = query.Where(x => x.Level == dto.Level);
        }


        if (dto.ParentId != null)
        {
            query = query.Where(x => x.ParentId == dto.ParentId);
        }

Теперь, похоже, 3.1 не может перевести это на SQL (я полагаю, вы не можете добавить Where после Select). Если я попытаюсь добавить Select после фильтрации, компилятор скажет мне, что он не может преобразовать IQueryable<BusinessUnit> в IQueryable<BuViewModel>. Если я пытаюсь явно объявить IQueryable<BuViewModel> query = ..., я должен написать Select перед Where предложениями (и это не будет работать). Какой здесь лучший подход?

1 Ответ

1 голос
/ 13 января 2020

Проблема начинается с этой строки. IQueryable создает запрос SQL, поэтому:

   .Select(x => new BUViewModel(x))

Iqueryable не может вызывать конструкторы. Чтобы исправить это, сделайте это вручную.

.Select(x=> new BUViewModel(){
               Id = x.Id,
               Name = x.Name // etc

            })

Но почему конструктор не работает? Потому что вы можете написать любой код, который вы будете sh в конструкторе. EF не сможет перевести на него SQL Запрос. Допустим, вы можете написать конструктор, подобный этому.

public BUViewModel(int id){
    var apiToken = _serviceCallApi(id);
}

Приведенный выше пример вызывает API, когда он создает объект (это просто пример). Невозможно перевести эту логику c на запрос. Существуют такие инструменты, как automapper, которые могут автоматически отображать объекты.

Полагаю, вы просто имели дело не с IQueryable, а с IEnumarable. Что неверно, потому что вы хотите, чтобы SQL отфильтровал данные для вас. Не загружать все в память.

...