Most efficient way to create a dynamic LINQ query

2019-07-26 22:20发布

问题:

This question already has an answer here:

  • Conditional Linq Queries 13 answers

I'm creating a web application that retrieves data from the database based on the criteria entered. The problem is that I have 10 different search fields and only one of them is required to be filled, the rest can be null.

So what I have is:

Textbox1
Textbox2
..
..
Textbox10

My current query is:

checked = false;
if (Textbox1.Text != null)
{
   result = //query here
   checked = true;
}

if (Textbox2.Text != null)
{
    if(checked==false)
    {
       result = //new query here
       checked = true;
    } 
    else
    {

        result = results.Where(...new query to filter Textbox2 from previous 
        query)
    }
}

and so on.

How can I build this in one query and ignore the textboxes that don't have values?

Thanks

回答1:

As you mentioned in your question you only need to narrow your query on each step.

var result = //query here

if (Textbox1.Text != null)
{
  result = result.Where(r=> r.x == Textbox1.Text);
}

if (Textbox2.Text != null)
{
  result = result.Where(r=> r.y == Textbox2.Text);
}
...

return result;


回答2:

An alternative approach is to do the null/empty check inside the query itself, using an || operator along with the conditional check if the text property has a value, inside parenthesis to form a "sub clause". Because the || operator will return true as soon as one side evaluates to true, and evaluation is done from left to right, always put the null/empty check first.

In this way, each "sub clause" returns true if the textbox text is null or empty, or it will returns the evaluation of the condition based on the text value of that textbox. Effectively, this "ignores" the text property for textboxes that are null or empty:

var result = data.Where(d => 
    (string.IsNullOrEmpty(Textbox1.Text) || d.X == Textbox1.Text) && 
    (string.IsNullOrEmpty(Textbox2.Text) || d.Y == Textbox2.Text) && 
    (string.IsNullOrEmpty(Textbox3.Text) || d.Z == Textbox3.Text));