【问题标题】:Only include in where condition if value is not null in Linq如果 Linq 中的值不为空,则仅包含在 where 条件中
【发布时间】:2020-02-21 04:41:25
【问题描述】:

我有一个很长的 sql,其中有多个 where 条件。我希望只有在传递的值不为 null 时才考虑 where 条件

灵巧

from b in _context.customer
           join d in _context.Address on b.id equals d.Id 
           join e in _context.units on d.Id equals e.Id
           where e.unitNumber == valueProvided)

select new modelAddress
              {
               address= address
              }

提供的值可以为空,因此我希望 where 条件不考虑 e.unitNumber。另外这只是一个例子,实际查询量很大

【问题讨论】:

  • 罗伯特的答案是正确的。您可能不喜欢它,但通过提取条件应用程序以便在将条件传递给 SQL 之前完成检查,确保了最佳查询。另一种方法是为每个可为空的条件添加类似where e.unitNumber = (valueProvided != null ? valueProvided : e.UnitNumber) 的条件。这会将这些条件传递给 SQL 来解决,从而减慢查询速度。仅仅因为你不同意他们就拒绝回答尝试是很糟糕的形式。

标签: sql entity-framework linq


【解决方案1】:

如果我很了解您想要做什么,我认为您可以在执行 Linq 操作后验证该属性,对吧?

如果没有,你可以这样做:

from b in _context.customer
           join d in _context.Address on b.id equals d.Id 
           join e in _context.units on d.Id equals e.Id
           where valueProvided.HasValue && e.unitNumber == valueProvided)

select new modelAddress
{
   address= address
}

你需要用那个Linq吗?你可以用Linq to SQL吗?

因为链接到 SQL,您可以使用以下代码:

list.Where(w => w.value != null).Where(anotherPredicate);

或者

list.Where(w => w.value.HasValue && anotherPredicate);

或者

list.FindAll(f => f.HasValue).Where(wherePredicate);

【讨论】:

  • 必须使用那个linq
【解决方案2】:

做你的基本查询(这看起来应该是导航属性):

var result = from b in _context.customer
       join d in _context.Address on b.id equals d.Id 
       join e in _context.units on d.Id equals e.Id

添加您的条件过滤器:

if (valueProvided != null)
    result = result.Where(e=>e.unitNumber == valueProvided);
if (valueProvided2 != null)
    result = result.Where(e=>e.somethingelse = valueProvided2);
...

添加您的分页(如果有):

result = result.Skip(pagesize * (currentPage-1)).Take(pagesize);

做你的预测:

var final = result.Select(r=>new modelAddress
          {
           address= r.address
          });

【讨论】:

  • 刚刚告诉你这是一个巨大的查询,不想包含if条件,它不仅仅是一个where条件
  • 所以您是说由于某种原因您不能在上面的基本查询中添加所有 where 条件,然后只包含一个 if 条件?你当然可以只使用 WHERE (valueProvided == null || e.unitNumber == valueProvided) 的等效项,但你的性能可能会受到影响,它的可扩展性不是很好,我不推荐它。
  • WHERE (valueProvided == null) 将不起作用,但 valueProvided 在数据库中不为空。我只想从查询中排除它
【解决方案3】:

我不知道您的所有查询以及您为什么需要这样过滤。不过我建议一种方法。

var filters = new List<Func<Customer, bool>>();
if (valueProvided != null) {
    filters.Add(a => a.unitNumber == valueProvided );
}

var filteredResult = new List<Customer>();
if (filters.Count == 0) {
    filteredResult = _context.customer.Select(s=>new modelAddress{ address=s.address }).ToList();
} else if (filters.Count == 1) {
    filteredResult = _context.customer.Where(filters[0]).Select(s=>new modelAddress{ address=s.address }).ToList();
} else {
    Func<Customer, bool> predicate = filters[0];
    for (int i = 1; i < filters.Count; i++) {
        //I use 'and' here but if you want to use 'or', it is also ok.
        predicate = customer=> predicate(customer) && filters[i](customer);
    }
    filteredResult = _context.customer.Where(predicate).Select(s=>new modelAddress{ address=s.address }).ToList();
}

我从我的上下文中转换了这个代码块并且运行良好。我只在 sql 分析器上看到我需要的东西。

【讨论】:

    【解决方案4】:

    如果您使用传统的查询方法,您会发现您可以根据收到的值应用的子句中的限制,我建议使用动态 linq 表达式绑定。

    您可以查看此博客以获取更多详细信息。 http://tomasp.net/blog/dynamic-linq-queries.aspx/

    我建议不要使用传统的 if else 或 switch case,因为这会随着系统的增长而增加复杂性

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      相关资源
      最近更新 更多