LINQ to SQL Where子句可选条件


72

我正在使用LINQ to SQL查询,并且遇到了一个问题,其中我有4个可选字段来过滤数据结果。可选地,我的意思是可以选择是否输入值。具体来说,一些文本框可能具有值或具有空字符串,而一些下拉列表可能具有选择值或可能没有值...

例如:

    using (TagsModelDataContext db = new TagsModelDataContext())
     {
        var query = from tags in db.TagsHeaders
                    where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                    select tags;
        this.Results = query.ToADOTable(rec => new object[] { query });
    }

现在,我需要添加以下字段/过滤器,但前提是它们由用户提供。

  1. 产品编号-来自另一个可以连接到TagHeader的表。
  2. 采购订单编号-TagsHeaders表中的一个字段。
  3. 订单号-与PO#类似,只是不同的列。
  4. 产品状态-如果用户是从下拉菜单中选择的,则需要在此处应用所选的值。

我已经拥有的查询效果很好,但是要完成该功能,需要能够在where子句中添加这4个其他项,只是不知道如何!


1
这里检查罗斯科,它可能已被回答已经.. http://stackoverflow.com/questions/11194/conditional-linq-queries
jlembke

Answers:


123

您可以对原始查询进行编码:

var query = from tags in db.TagsHeaders
                where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                select tags;

然后根据条件,添加其他where约束。

if(condition)
    query = query.Where(i => i.PONumber == "ABC"); 

我不确定如何使用查询语法对此进行编码,但id确实适用于lambda。还适用于初始查询的查询语法和辅助过滤器的lambda。

您还可以包括一个扩展方法(如下),我将其编码了一段时间,以包括条件where语句。(不适用于查询语法):

        var query = db.TagsHeaders
            .Where(tags => tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()))
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE)
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE)
            .WhereIf(condition1, tags => tags.PONumber == "ABC")
            .WhereIf(condition2, tags => tags.XYZ > 123);

扩展方法:

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

这是IEnumerables的相同扩展方法:

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

1
+1确实可以清理代码并更好地进行通信
jlembke

3
+10非常感谢您的回答。就是我在看 非常感谢您抽出宝贵的时间进行此操作。
RSolberg

2
Ryan仍在SJH / PeaceHealth工作。爱我的工作。好人 你在FB吗?我们确实应该在其他地方进行此对话。阿罗宾逊/ Gmail。
andleer

2
@andleer,老兄,你真棒,你不知道自己救了多少个失落的灵魂:)
DevMania 2012年

2
@Ryan,很乐意为此提供帮助。
andleer 2012年

31

只需要对参数的存在使用条件检查。例如:

where (string.IsNullOrEmpty(ProductNumber) || ProductNumber == tags.productNumber)

这样,如果未输入产品编号,则表达式在所有情况下都将返回true,但是如果输入,则仅在匹配时返回true。


+1很好。我曾想过类似的事情
jlembke

+1我试图找到一种“条件性位置”的优雅解决方案,在这种情况下,我有多个联接,结果从联接表返回记录。像魅力一样工作!
AidaM 2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.