【问题标题】:Smarter where clause?更聪明的 where 子句?
【发布时间】:2011-09-23 10:47:27
【问题描述】:

我最近一直在试验 LINQ to SQL,并有一个简短的问题。 基本前提是我有一个搜索请求,其中包含我用来搜索包含汽车的数据库的品牌和型号。

我的 Where 子句的表达式如下所示:

.Where(c => c.make == search.make  && c.model == search.model)

当我的搜索同时包含品牌和型号时,这很好。当它只包含一个品牌(反之亦然)而不包含两个搜索字段时,就会出现问题。我希望它退回所有该品牌的汽车,但它没有退回任何汽车。

我假设这是因为它正在寻找 make 加上一个 null 或空的模型?

除了使用一系列“如果非空附加到查询”类型的步骤手动构建查询之外,是否有一种优雅的方法来解决这个问题?

【问题讨论】:

  • 我也会感兴趣,现在我用 If Else 解决了这种问题,然后在这两种情况下我执行不同的 Linq to Sql 查询。

标签: c# linq linq-to-sql


【解决方案1】:

你试过了吗:

.Where(c => (search.make == null || c.make == search.make)  && (search.model == null || c.model == search.model))

更新:这里实际上对一般问题和干净的解决方案有很好的处理: LINQ to SQL Where Clause Optional Criteria。共识似乎是扩展方法是最干净的。

【讨论】:

  • 谢谢,这是有道理的。我知道会有更好的方法,只是没有跳出来……这是漫长的一周:)
【解决方案2】:
.Where(c => (search.make == null || c.make == search.make) && 
            (search.model == null || c.model == search.model))

【讨论】:

  • 这不是在做错事吗? (获取型号为空的汽车,即使搜索的是特定品牌和型号?)
  • 谢谢@Tao,我误解了这个问题。相应地更正了我的答案。
  • @Boob:如果成功了,请给 Tao 的荣誉,他一开始就做对了。
【解决方案3】:

IMO,拆分它:

IQueryable<Car> query = ...
if(!string.IsNullOrEmpty(search.make))
    query = query.Where(c => c.make == search.make);
if(!string.IsNullOrEmpty(search.model))
    query = query.Where(c => c.model== search.model);

这会生成最合适的 TSQL,因为它不会包含多余的 WHERE 子句或其他参数,从而允许 RDBMS (单独)优化“make”、“model”和“make and model”查询。

【讨论】:

    【解决方案4】:

    你可以这样写:

    .Where(c => c.make == search.make ?? c.make && c.model == search.model ?? c.model)
    

    【讨论】:

    • 谢谢保罗,你能解释一下这里发生了什么吗?我对 LINQ 和 LAMBDA 的东西还很陌生,还没有看到“??”以前用过的语法吗?
    • ?? 是合并运算符。如果左侧的值为空,它将使用右侧的值。相当于(x == null ? y : x)
    【解决方案5】:

    这应该可行。

    .Where(c => 
        (search.make == null || c.make == search.make) &&
        (search.model == null || c.model == search.model))
    

    【讨论】:

      【解决方案6】:
      .Where(c => (string.IsNullOrEmpty(c.make) || c.make == search.make) && 
                  (string.IsNullOrEmpty(c.model) || c.model == search.model))
      

      【讨论】:

        【解决方案7】:
        .Where(c => (string.IsNullOrEmpty(search.make) || c.make == search.make) &&
                    (string.IsNullOrEmpty(search.model) || c.model == search.model))
        

        假设属性是字符串。

        【讨论】:

        • 实际上,在重新阅读问题时,可能甚至不需要调用 IsNullOrEmpty。取决于您如何创建搜索对象。
        【解决方案8】:
        Where(c => (search.make == null || c.make == search.make) && 
                   (search.model == null || c.model == search.model))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-08
          • 1970-01-01
          • 1970-01-01
          • 2022-12-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-07
          • 1970-01-01
          相关资源
          最近更新 更多