2012-02-03 18 views
10

Estoy utilizando linq para entidades (EF). Tengo un constructor que toma 4 parámetros de cadena. Dependiendo de qué parámetro no es nulo, tengo que construir la consulta de linq. Puedo hacer con declaraciones if else pero también tengo otro constructor con 10 parámetros, en ese caso habrá muchas combinaciones para verificar.Cláusula dynamic where en Linq para Entidades

Ejemplo:

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; 
} 

En lo anterior cláusula where no debería haber controles de condición sólo si el parámetro no es nulo. es decir., si P2 es nulo entonces la cláusula where debe ser similar

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

si P2 y P3 son nulos entonces

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

Puede alguien decirme cómo manejar esto. si es posible, se puede dar el código de ejemplo para este

+0

duplicado Posible de http://stackoverflow.com/questions/697345/linq-to-sql- need-dynamic-where-clause-over-relational-tables-help? rq = 1 –

Respuesta

11

Linq's DeferredEjecución para rescatar. La consulta de Linq no se ejecuta a menos que se soliciten los datos.

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(); 
+0

si así lo hacemos, cargaremos una gran cantidad de datos en prod y luego están tomando un subconjunto de esto. ¿Podemos obtener el subconjunto directamente? – Deepak

+3

La consulta se ejecuta ** NO ** hasta que se crea la cláusula where. Inn el código anterior la consulta se construye hasta la última línea y es donde se ejecuta. Puede bloquear esto ejecutando SQL Profiler. –

+0

Sí, estás en lo cierto. Puedo usar tu código y está funcionando perfectamente. – Deepak

3

Usted puede encadenar los métodos según sea necesario:

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" 
} 

El SQL resultante debe ser el mismo que si se ponen todos en una sola sentencia.

+1

si hacemos esto cargaremos una gran cantidad de datos en prod y luego estamos tomando un subconjunto de ellos. ¿Podemos obtener el subconjunto directamente de lo contrario estamos cargando datos innecesarios – Deepak

+1

@Deepak No, no lo hará. Lo bueno de IQueryable es que no "carga los datos": LINQ utiliza la ejecución diferida, y con EF, traduce la "consulta" final en una sola instrucción SQL. Este será el mismo resultado. –

+1

@Deepak Para obtener más información, consulte: http://stackoverflow.com/questions/1578778/using-iqueryable-with-linq/1578977#1578977 –

2

Siempre se puede construir la consulta en pedazos y tomar ventaja de ejecución de la consulta retardada:

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); 
} 
+0

si hacemos esto cargaremos gran cantidad de datos en prod y luego estamos tomando un subconjunto de ellos. ¿Podemos obtener el subconjunto directamente? De lo contrario estamos cargando datos innecesarios – Deepak

+1

@Deepak - No cargará ningún dato en absoluto. LINQ no ejecuta la consulta hasta que realmente usa los datos. En el momento en que se ejecuta la consulta, ya tendrá las cláusulas where adecuadas para cargar solo los datos que necesita. –

Cuestiones relacionadas