Linq dynamically adding where conditions

2020-02-06 04:16发布

I have a gridview which has drop down boxes in each header for filtering. Each filter is loaded with the distinct values from its column when loaded. At run time, I add "ALL" to allow the user to select all from that field. I am trying to build the linq statement dynamically to ignore the field if the drop down box is set to "ALL". Is this possible? I want to see if I can do this in one single statement. The example below only shows 2 dropdown boxes, but my actually case has up to 5.

If I choose to use if then statements, I end up with spaghetti code.

DropDownList drpOwners = this.grdOtherQuotes.HeaderRow.FindControl("drpOwners") as DropDownList;                     
DropDownList drpCompanyName = this.grdOtherQuotes.HeaderRow.FindControl("drpCompanyName") as DropDownList;

var filteredList = (from x in allQuotes
                          where (drpOwners.SelectedValue != ALL) ? x.SalesRepFullName == drpOwners.SelectedValue:true                                    
                                && drpCompanyName.SelectedValue != ALL ? x.CompanyName == drpCompanyName.SelectedValue: true
                          select x);

标签: c# linq
3条回答
倾城 Initia
2楼-- · 2020-02-06 04:29

You could create a helper method that handles the All logic. Something like:

private bool CompareSelectedValue(string value, string dropDownValue)
{
  if(dropDownValue == "ALL")
    return true;
  else
    return value == dropDownValue;
}

Then your query could be:

var filteredList = (from x in allQuotes
                          where (CompareSelectedValue(x.SalesRepFullName, drpOwners.SelectedValue)                                    
                                && CompareSelectedValue(x.CompanyName, drpCompanyName.SelectedValue)
                          select x);
查看更多
The star\"
3楼-- · 2020-02-06 04:38

Create extension method(s) which encapsulate the where logic so it looks cleaner:

var filteredList = allQuotes.WhereDropOwnersAreContained()
                            .WhereCompanyIsContained()
                            ...
                            ;
查看更多
手持菜刀,她持情操
4楼-- · 2020-02-06 04:43

Personally, I'd find having this broken up to be simpler:

IEnumerable<Quote> filteredList = allQuotes;
// If using EF or LINQ to SQL, use: IQueryable<Quote> filteredList = allQuotes;
if (drpOwners.SelectedValue != ALL) 
   filteredList = filteredList.Where(x => x.SalesRepFullName == drpOwners.SelectedValue);
if (drpCompanyName.SelectedValue != ALL) 
   filteredList = filteredList.Where(x => x.CompanyName == drpCompanyName.SelectedValue);
// More conditions as needed

This really isn't any longer, and it's far simpler to follow.


If you really wanted to be able to write this as a "one-liner", you could make an extension method to build the query. For example, if using Entity Framework:

static IQueryable<T> AddCondition(this IQueryable<T> queryable, Func<bool> predicate, Expression<Func<T,bool>> filter)
{
     if (predicate())
         return queryable.Where(filter);
     else
         return queryable;
}

This would then let you write this as:

var filteredList = allQuotes
                     .AddCondition(() => drpOwners.SelectedValue != ALL, x => x.SalesRepFullName == drpOwners.SelectedValue)
                     .AddCondition(() => drpCompanyName.SelectedValue != ALL, x.CompanyName == drpCompanyName.SelectedValue);

You could, of course, take this even further, and make a version that hard-wires the predicate to check a combo box against "ALL", making the predicate shorter (just the combo box).

查看更多
登录 后发表回答