2012-06-16 7 views
6

He creado un método de extensión sobre el tipo IQueryable, que toma un subconjunto de entidades y las filtra sobre algunos criterios. Mi problema es que no puedo devolver una expresión de Unión hecha de las variables, sin que todas se inicialicen primero. Los valores nulos, como aprears, no son válidos.¿cómo debo inicializar las variables IQueryable, antes de usar una expresión de Unión?

public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) 
    { 
     IQueryable<Person> q1 = null; 
     IQueryable<Person> q2 = null; 
     IQueryable<Person> q3 = null; 
     IQueryable<Person> q4 = null; 

     foreach (var value in hairColors) 
     { 
      switch (value) 
      { 
       case "1": 
        q1 = subQuery.Where(p => p.HairColor_bright == true); 
        break; 
       case "2": 
        q2 = subQuery.Where(p => p.HairColor_brown == true); 
        break; 
       case "3": 
        q3 = subQuery.Where(p => p.HairColor_dark == true); 
        break; 
       case "4": 
        q4 = subQuery.Where(p => p.HairColor_red == true); 
        break; 
      } 
     } 
     return q1.AsQueryable().Union(q2.AsQueryable()).Union(q3.AsQueryable()).Union(q4.AsQueryable()); 
    } 

El bloque de código que se presenta es parte de varios más, y cada uno produce un subconjunto de datos, transportada a un método de filtrado posterior de esta manera:

results = persons.FilterGender(vm.gender).FilterAge(vm.age).FilterHeight(vm.height)...... 

Respuesta

3

No Llame Unión cuando una de las argumentos es nulo.

¿Qué significa una "consulta nula" para usted? Si eso significa "no filas", simplemente no lo vincule. Si significa "todas las filas", no es necesario que se vincule, ya que solo puede tomar la consulta subyacente no filtrada.

De esta manera:

var result = new [] { q1, q2, q3, q4, }.Where(query => query != null).Aggregate(Queryable.Union); 

Se trata de utilizar LINQ a objetos para construir una consulta LINQ a SQL.

Una nueva versión:

var result = dataContext.Persons.Where(_ => false); 
if(q1 != null) result = result.Union(q1); 
if(q2 != null) result = result.Union(q2); 
if(q3 != null) result = result.Union(q3); 
if(q4 != null) result = result.Union(q4); 

El optimizador de consultas de SQL Server eliminará la primera consulta ficticia para que tenga tiempo de ejecución sin costo en absoluto.

+0

Entonces, ¿cómo debo condicionar el rendimiento de Union con variables no nulas? –

+0

He agregado una propuesta. – usr

+0

Gracias 'usr'. ¿Puedes pensar en una forma más simple e intuitiva de acceder a mi problema? –

1
public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) 
{ 
    var result = new Person[] { }.AsQueryable(); 
    var contains = new Dictionary<string, Expression<Func<Person, bool>>>(); 

    contains.Add("1", p => p.HairColor_bright); 
    contains.Add("2", p => p.HairColor_brown); 
    contains.Add("3", p => p.HairColor_dark); 
    contains.Add("4", p => p.HairColor_red); 

    foreach (var color in hairColors) 
    { 
     result = subQuery.Where(contains[color]).Union(result); 
    } 

    return result; 
} 
+0

Lo he intentado, y vino con este error: "Este método es compatible con LINQ a la infraestructura de la entidad y no está destinado a ser utilizado directamente desde su código". ver el tema de la regularización: http://social.msdn.microsoft.com/Forums/is/adodotnetentityframework/thread/3962b925-fe1e-4b96-ade3-5cb3b4be4511 –

Cuestiones relacionadas