2012-04-18 30 views
11

Actualmente estoy escribiendo una función de búsqueda en ASP.NET MVC 4 con Entity Framework. Sin embargo, he llegado a un obstáculo para el cual solo puedo encontrar soluciones "malas".consulta de linq a sql con múltiples donde los parámetros

Mis funciones de búsqueda lleva de nuevo un modelo que consta de 4 parámetros:

String Name 
String Street 
String Code 
String Province 

List<Query> query = (from t in Model select t).ToList(); 

Ahora me gustaría filtrar en mi entrada de búsqueda. Sin embargo, un usuario puede decidir completar tantos campos de búsqueda como sea posible. Él puede decidir usar Nombre y Calle, o Nombre, Calle y Provincia, o ...

La única solución real que pude encontrar consiste en hacer mi consulta y IQueryable y verificar si un campo se ha llenado o no con un if, luego use un .Where para actualizar la consulta. Como esto daría actualmente m 5 consultas, me pregunto si falta o no una mejor solución aquí.

Gracias por ayudarme.

Respuesta

22

Si entiendo correcto. Es posible que desee algo como esto:

string Name; 
string Street; 
string Code; 
string Province; 
var query=(from t in Model select t); 
if(Name!=null) 
{ 
    query=query.Where (q =>q.Name==Name); 
} 
if(Street!=null) 
{ 
    query=query.Where (q =>q.Street==Street); 
} 
if(Code!=null) 
{ 
    query=query.Where (q =>q.Code==Code); 
} 
if(Province!=null) 
{ 
    query=query.Where (q =>q.Province==Province); 
} 
List<Query> ls = query.ToList(); 

Tendrá una IQueryable cuando se agrega el declaraciones donde y cuando lo hace el ToList() que SQL se ejecutará.

actualización

Para responder a los comentarios de Luis Hernández. Así que así es como funciona. Cuando selecciona desde el modelo en este caso, el tipo de colección es IQueryable. Esto significa que no se ha ejecutado contra la base de datos. Para que la consulta se ejecute, debe aplicar algunos de los métodos finales. Decirle a linq que realmente hará la llamada a la base de datos. Estos son, por ejemplo,

ToList() 
FirstOrDefault() 
SingleOrDefault() 
Single() 
First() 
ToDictionary() 

Así que cuando añadimos las cláusulas cuando sin utilizar ToList(). No hay ejecución de la consulta.

Por favor, intente la consulta en LinqPad

+0

Sí, esa es la solución que encontré en línea. Me preguntaba si existe o no una forma más clara de codificar esto. – whodares

+0

Si quieres quedarte 'IQueryable'. Entonces esto es lo que creo que es la manera de hacerlo – Arion

+0

Puede haber más código, pero este es el más optimizado (y probablemente el mejor). Verifique la consulta SQL resultante en [linqpad] (http://www.linqpad.net/) – mshsayem

0

Usted CASN intentar algo como esto

from cars in tblCars 
where (cars.colorID == 1) && (cars.Wieght > 500) && (cars.Active == true) 
select cars; 
2

Utilice la clase de filtro Entidad a encontrar aquí: https://servicelayerhelpers.codeplex.com/SourceControl/changeset/view/32810#537055

por lo que primero especifique el filtro y después de eso solo aplícalo a tu consulta.

Ejemplo:

var filter = EntityFilter 
.Where(c => c.Name == came) 
.Where(c => c.City == city); 

var customers = FindCustomers(filter); 

Customer[] FindCustomers(IEntityFilter filter) 
{ 
var query = context.Customers; 
query = filter.Filter(query); 
return query.ToArray(); 
} 

más información en: https://cuttingedge.it/blogs/steven/pivot/entry.php?id=66

0

solución de Arion es por supuesto muy buena, traté de que sea un poco menos repetitivas utilizando la reflexión, creo que sirve.

 Type myType = myObject.GetType(); 
     IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties()); 

     foreach (PropertyInfo prop in props) 
     { 
      object propValue = prop.GetValue(myObject, null); 
      if (propValue != null) 
      { 
       query = query.Where(q => prop.GetValue(q, null) == propValue); 
      } 
     } 

EDIT:

He editado para que funcione en todas las propiedades. por supuesto, todavía necesita algunas cosas para que esto funcione, pero una vez que comprenda cómo trabajar con él, puede usarlo como una utilidad para todo su código, en lugar de codificarlo para cada tipo

+0

Gracias por la respuesta, pero esto solo funciona para el valor del nombre que ha especificado. Como también tengo otros 3 valores, no veo cómo esto podría funcionar. – whodares

Cuestiones relacionadas