1

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

joepr
  • 21
  • 1
  • 5
  • Why a one liner. It would be much more complex and much less efficient. As long as you keep the result as 'IEnumerable` the query will be piped and executed when accessed. – Franck Jun 07 '18 at 19:41
  • I think looping through controls to get textBoxes, then check if they have values or not, better than check each textBox a time. – Kaj Jun 07 '18 at 20:18
  • Even though you didn't provide much context, I'd seriously recommend looking into `LinqDataSource` paired with a `QueryExtender` control and optionally autogenerated filter controls based on model metadata usind DynamicData. There is usually zero need to manually code what you are doing there and you can get incredibly efficient results using what I mentioned. – julealgon Jul 01 '18 at 03:24

2 Answers2

2

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;
Elyas Esna
  • 625
  • 4
  • 19
1

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));
Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • using `||` this way may reduce the speed of the query. because of the right-hand side of `||` will execute either left-hand side is true or not, so it could be better to write the where clause this way: `data = string.IsNullOrEmpty(Textbox1.Text) ? data.Where(d => d.X == Textbox1.Text) : data;` – Muhammad Vakili Jun 08 '18 at 06:02
  • 1
    @muhammad no, that's not true. The second operand is evaluated only if the first operand evaluates to false. See: https://msdn.microsoft.com/en-us/library/f355wky8.aspx – Rufus L Jun 08 '18 at 13:54
  • @Muhammadvakili no, that's not true. The second operand is evaluated only if the first operand evaluates to false. See: https://msdn.microsoft.com/en-us/library/f355wky8.aspx – Rufus L Jun 08 '18 at 16:20