【问题标题】:LINQ apply filter in where clause only if parameter value greater than Zero?LINQ仅在参数值大于零时在where子句中应用过滤器?
【发布时间】:2018-02-21 08:33:11
【问题描述】:

我正在使用 LINQ 从数据库中检索记录。一切正常,除了我需要在单个查询中应用不同的过滤器。如果参数不是Null 大于零,则显示所有员工记录。否则,如果它们是 Null 或小于零,则不要应用过滤器。以下是我目前的做法:

public ActionResult GetEmployee(int? JobTitleId, int? GenderId)
{
   var Emloyees = db.Employees.ToList();

   if(JobTitleId > 0)
   {
      Emloyees = Emloyees.Where(e => e.JobTitleId == JobTitleId).ToList();
   }

   if(GenderId> 0)
   {
      Emloyees = Emloyees.Where(e => e.GenderId == GenderId).ToList();
   }

}

有没有办法将此应用于单个查询?我想做如果JobTitleId 和GenderId 是Null 然后显示其他记录,否则,过滤它们。

【问题讨论】:

  • 使用if(JobTitleId.HasValue)等会更好,因为它可以为空,但你做的是正确的方法
  • 如果您的查询会更复杂,这个链接可以帮助你Build Where Clause Dynamically in Linq
  • 请注意,您还应该删除查询中的.ToList()(如果您确实想将其设为List<T>,请在所有查询之后执行此操作)

标签: c# .net asp.net-mvc entity-framework linq


【解决方案1】:

您应该将谓词添加到IQueryable,即删除ToList:

var employees = db.Employees.AsQueryable();

if (JobTitleId.GetValueOrDefault() > 0)
{
   employees = employees.Where(e => e.JobTitleId == JobTitleId);
}

等等

当您调用employees.ToList()之后时,谓词将被转换为 SQL,您将从数据库中提取更少的数据。上面的语句只构建查询而不是执行它。

【讨论】:

  • 不,这是因为必须将 employees 强制转换为 IQueryable 才能通过 employees = employees... 语句对其进行扩展。与首先通过 ToList 从数据库中提取所有员工相比,整个方法(扩展 IQueryable)在性能方面更好。
  • 为了获得更好的性能,我使用AsQueryable 并应用我的过滤器,然后使用ToList?
  • 是的,就是这样。
  • 请查看this question。与上述问题有关。
【解决方案2】:

您可以编写一个扩展方法来有条件地应用过滤器:

public static IQueryable<T> WhereIf<T>(
   this IQueryable<T> source, bool condition, 
   Expression<Func<T, bool>> predicate)
{
    if (condition)
        return source.Where(predicate);
    else
        return source;
}

用法:

var employees = db.Employees
   .WhereIf(JobTitleId.HasValue, e => e.JobTitleId == JobTitleId)
   .WhereIf(GenderId.HasValue, e => e.GenderId == GenderId)
   .ToList();

此外,对于可为空的整数,请使用 HasValue 而不是与 0 进行比较。

【讨论】:

  • 这是一个不错的小扩展方法。它使代码非常简洁。
  • 多年来一直在寻找这样的东西。很好的建议
【解决方案3】:

希望这能解决,

         List<Employee> emplist = new List<Employee>();
            emplist.Add(new Employee() {EmpName="A",JobTitleId=0,GenderId=0 });
            emplist.Add(new Employee() { EmpName = "B", JobTitleId = 1, GenderId = 0 });
            emplist.Add(new Employee() { EmpName = "C", JobTitleId = 0, GenderId = 1 });
            emplist.Add(new Employee() { EmpName = "D", JobTitleId = 1, GenderId = 1 });
            int jobid = 1;
            int genderid = 1;
            var result = from em in emplist where ((em.JobTitleId > 0 && em.JobTitleId == jobid) ||  (em.GenderId > 0 && em.GenderId == genderid)) select em;           
            foreach (Employee emp in result)
                Console.WriteLine(emp.EmpName);
            Console.ReadKey();

【讨论】:

    【解决方案4】:

    你可以这样试试。

    Emloyees = Emloyees.Where(e=> (JobTitleId > 0 && e.JobTitleId == JobTitleId) || e.GenderId == GenderId).ToList();
    

    【讨论】:

      【解决方案5】:

      我猜你可以这样做:

      var emloyees = db.Employees.Where(e => (!JobTitleId.HasValue && !GenderId.HasValue) || (JobTitleId > 0 && e.JobTitleId == JobTitleId) || (GenderId > 0 && e.GenderId == GenderId))
      

      但这使得它比您当前的解决方案复杂得多。

      使用 if 语句构建 LINQ 通常是可行的方法。

      【讨论】:

      • 复杂得多这样,空检查成为 SQL 查询的一部分,不必要地困扰数据库的查询优化器。
      • 这是一个例子。我有很多带有很多参数的函数。
      猜你喜欢
      • 2014-09-19
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 1970-01-01
      • 2015-04-18
      • 1970-01-01
      相关资源
      最近更新 更多