Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic where clause in Linq to Entities

I'm using linq to entities(EF). I have a constructor which takes 4 string parameters. Depending on what parameter is not null I have to build the linq query. I can do with if else statements but i also has other constructor with 10 parameters in that case there will be many combinations to check.

Example:

Constructor(p1,p2,p3,p4)
{
  var prod= from p in ctxt.products.expand("items\details")
            where p.x==p1 && p.xx==p2 && p.xxx==p3 && p.xxxx==p4
            select p;
}

In the above where clause there should be condition checks only if the parameter is not null. ie., if p2 is null then the where clause should look like

where p.x==p1 && p.xxx==p3 && p.xxxx==p4

if p2 and p3 are null then

where p.x==p1 && p.xxxx==p4

Can anyone tell me how to handle this. if possible can you give sample code for this

like image 563
Deepak Avatar asked Feb 03 '12 00:02

Deepak


3 Answers

You could always build the query in pieces and take advantage of delayed query execution:

public Constructor(int? p1, int? p2, int? p3, int? p4)
{
    var prod = ctxt.products.expand("items\details");

    if(p1 != null)
        prod = prod.Where(p.x == p1);

    if(p2 != null)
        prod = prod.Where(p.xx == p2);

    if(p3 != null)
        prod = prod.Where(p.xxx == p3);

    if(p4 != null)
        prod = prod.Where(p.xxxx == p4);
}
like image 169
Justin Niessner Avatar answered Nov 11 '22 02:11

Justin Niessner


Linq's DeferredExecution to rescue. Linq query is not executed unless the data is requested from it.

var prod = from p in ctxt.products.expand("items\details")
        select p;

if (p1 != null)
{
    prod = prod.Where(p => p.x == p1);
}

if (p2 != null)
{
    prod = prod.Where(p => p.xx == p2);
}

// Execute the query

var prodResult = prod.ToList();
like image 43
amit_g Avatar answered Nov 11 '22 02:11

amit_g


You can chain the methods as needed:

 YourType(string p1, string p2, string p3, string p4)
 {
      var prod = ctxt.Products.Expand("items\details");

      if (!p1.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.x == p1);
      if (!p2.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.xx == p2);

      // ....

      // use "prod"
 }

The resulting SQL should be the same as if you put them all in a single statement.

like image 3
Reed Copsey Avatar answered Nov 11 '22 01:11

Reed Copsey