Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing conditional 'if' statements within a LINQ queries 'where' statement

Tags:

c#

linq

I'm trying to figure out a way of querying an object in my datamodel and include only those parameters that are not null. Like below:

public List<Widget> GetWidgets(string cond1, string cond2, string cond3)
{
    MyDataContext db = new MyDataContext();
    List<Widget> widgets = (from w in db.Widgets
                            where 
                                ... if cond1 != null w.condition1 == cond1 ...
                                ... if cond2 != null w.condition2 == cond2 ...
                                ... if cond3 != null w.condition3 == cond3 ...
                            select w).ToList();
    return widgets;
}

Since the widgets table can get very large, I'd like to avoid doing this:

public List<Widget> GetWidgets(string cond1, string cond2, string cond3)
{
    MyDataContext db = new MyDataContext();
    List<Widget> widgets = db.Widgets.ToList();

    if(cond1 != null)
        widgets = widgets.Where(w => w.condition1 == cond1).ToList();

    if(cond2 != null)
        widgets = widgets.Where(w => w.condition2 == cond2).ToList();

    if(cond3 != null)
        widgets = widgets.Where(w => w.condition3 == cond3).ToList();

    return widgets;
}

I've looked at several example but don't really see anything that matches what I need to do.

like image 939
Andy Evans Avatar asked Sep 21 '10 13:09

Andy Evans


People also ask

How do I add and condition in LINQ query?

If you do not call ToList() and your final mapping to the DTO type, you can add Where clauses as you go, and build the results at the end: var query = from u in DataContext. Users where u. Division == strUserDiv && u.

Can we use multiple where clause in LINQ?

Filter collections using Where clause in C#. A single query expression may have multiple where clauses.

Which clause is used for conditions in LINQ?

In LINQ, we can use Where() clause in the query to define multiple conditions, as shown below. This is how we can use LINQ where clause filtering operator to filter data based on conditions.

What does LINQ use to implement the query operators?

The LINQ to Objects provider is used for in-memory collections, using the local query execution engine of LINQ. The code generated by this provider refers to the implementation of the standard query operators as defined on the Sequence pattern and allows IEnumerable<T> collections to be queried locally.


2 Answers

What you want to avoid is actually executing the query until you are ready:

public List<Widget> GetWidgets(string cond1, string cond2, string cond3)
{
    MyDataContext db = new MyDataContext();
    var widgets = db.Widgets;

    if(cond1 != null)
        widgets = widgets.Where(w => w.condition1 == cond1);

    if(cond2 != null)
        widgets = widgets.Where(w => w.condition2 == cond2);

    if(cond3 != null)
        widgets = widgets.Where(w => w.condition3 == cond3);

    return widgets.ToList();
}

Note how the ToList calls are removed. The query is not executed until you start iterating over it. Invoking ToList will force that to happen, so that the result can be put into a List<> and returned. I would even suggest to change the return value of the method to IEnumerable<Widget> and skipping the ToList call in the end:

public IEnumerable<Widget> GetWidgets(string cond1, string cond2, string cond3)
{
    MyDataContext db = new MyDataContext();
    var widgets = db.Widgets;

    if(cond1 != null)
        widgets = widgets.Where(w => w.condition1 == cond1);

   // [...]

    return widgets;
}

That way the calling code gets to decide when to execute the query (it may even add more conditions before doing so).

like image 67
Fredrik Mörk Avatar answered Oct 03 '22 22:10

Fredrik Mörk


Use an "or gate": preface every widget condition test with an "||" and a check to see if we're using that condition or not. If we're not, the second half of the "or" isn't evaluated. That's why it's a gate -- we don't go any further if the first part evaluates to true.

If I were writing it, I'd do it like below. I used the var syntatic sugar to hold LINQ query and moved the ToList() to the end.

public List<Widget> GetWidgets(string cond1, string cond2, string cond3) 
{ 
    MyDataContext db = new MyDataContext(); 
    var widgets = from w in db.Widgets 
                  where (cond1 == null || w.condition1 == cond1)
                     && (cond2 == null || w.condition2 == cond2)
                     && (cond3 == null || w.condition3 == cond3)
                  select w;
    return widgets.ToList();
} 

edit: grammar

like image 33
curveship Avatar answered Oct 03 '22 22:10

curveship