EF Core 3.1-如何根据参数进行过滤?

时间:2020-01-13 10:05:08

标签: asp.net-core entity-framework-core ef-core-3.1

在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 个答案:

答案 0 :(得分:1)

问题从此行开始。 IQueryable构造一个SQL查询,因此:

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

Iqueryable无法调用构造函数。因此,要手动修复该问题。

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

            })

但是为什么构造函数不起作用?因为您可以在构造函数中编写所需的任何代码。 EF无法将其转换为SQL查询。假设您可以编写这样的构造函数。

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

例如,上面的示例在构造对象时调用了一个api(仅是示例)。不可能将此逻辑转换为查询。有诸如automapper之类的工具可以自动映射实体。

我的猜测很简单,您不是在处理IQueryable,而是在处理IEnumarable。这是不正确的,因为您希望SQL为您过滤数据。不要将所有内容都加载到内存中。

相关问题