如何在LINQ中动态添加.Where()子句

时间:2020-01-29 12:37:38

标签: c# linq

我有一个方法:
我定义了一个表达式,仅当输入参数userType具有值时,该表达式才在linq查询中。

public Institution GetInstitutionWithServices(int institutionId, UserTypes? userType)
{
  Expression<Func<Service, bool>> serviceUserTypeFilter = (s => true);

  if (userType.HasValue)
  {
    serviceUserTypeFilter = (s => s.UserType == userType.Value);
  };

  var query = _dbContext.Institution.Include(a => a.Services)
                                    .Where(a => a.Id == institutionId)
                                    .Select(m => new Institution
                                     {
                                       Id = m.Id,
                                       Name = m.Name
                                    .Where(x => x.Status == Service.ServiceStatus.Published) 
                                     //&& userType.HasValue ? x.UserType == userType.Value : false )
                                    .Where(serviceUserTypeFilter)
                                    .ToList()
                                    }).FirstOrDefault();
  return query;
}

我不知道如何为具有外键的其他表(数据库上下文)添加过滤器。
它具有服务。
在已注释的部分中,我需要调用thorugh表达式,因为该代码导致空引用异常
我得到的这段代码错误是:

错误CS1503
参数2:无法从“ System.Linq.Expressions.Expression<System.Func<Test001.Domain.Service, bool>>”转换为“ System.Func<Test001.Domain.Service, bool>
Test001.Repositories

2 个答案:

答案 0 :(得分:2)

在定义了主查询之后,并没有阻止您添加.Where子句的情况:

 var query = _dbContext.Institution.Include(a => a.Services);
 if(something)
 {
    query = query.Where(a => a.Id == institutionId);
 }

 ...
 var results = query.ToList();  // <-- This 'executes' the query

 etc

在实际执行查询之前的任何时候(在您的情况下为.ToList()),您都可以继续添加其他linq子句(.Where,.OrderBy等)。

答案 1 :(得分:0)

您的代码似乎包含错误(“ ..m.Name.Where(x => x.Status ...”是什么??),但我想您需要类似以下解决方案:

Expression<Func<Service, bool>> servicesWhereClause;
        if (!userType.HasValue)
            servicesWhereClause = x => x.Status == Service.ServiceStatus.Published;
        else
            servicesWhereClause = x => x.Status == Service.ServiceStatus.Published
                && x.UserType == userType.Value;
        var result = _dbContext.Institution
            .Include(a => a.Services)
            .Where(a => a.Id == institutionId)
            .Select(i => new
            {
                Institution = i,
                Services = i.Services.Where(servicesWhereClause)
            })
            .ToList()
            .Select(anon => new Institution
            {
                Id = anon.Id,
                Name = anon.Name,
                // etc...
                Services = anon.Services
            })
            .ToList();

如果您想一次获取带有父记录的过滤后的子记录,则应使用匿名返回类型并在此之后进行映射。不幸的是,ef不会追踪此类记录。