Filtrar / Buscar usando múltiples campos – ASP.NET MVC

Estoy usando ASP.NET MVC con EF 6 .

Tengo una página de inventario que muestra toda la información sobre artículos en existencia. Ahora quiero filtrar los registros también.

En la imagen de abajo tengo 3 opciones. Podría filtrar por cada opción, una a la vez o por combinación de dos o con las tres.

Estaba pensando en escribir linq query para cada una de las opciones seleccionadas. Pero esto no sería posible si aumenta la opción de filtro. Hay una forma mejor de hacerlo.

¡Gracias!

enter image description here

Esto es lo que hice en mi controlador. (Actualmente el menú desplegable tiene dos opciones, excluyendo: “- seleccionar una -“)

public ActionResult StockLevel(string option, string batch, string name) { if (option != "0" && batch == "" && name == "") { if(option == "BelowMin") { List stk = (from s in db.Stocks where s.Qty < s.Item.AlertQty select s).ToList(); return View(stk); } else { List stk = (from s in db.Stocks where s.Qty == s.InitialQty select s).ToList(); return View(stk); } } if (option == "0" && batch != "" && name == "") { List stk = (from s in db.Stocks where s.BatchNo == batch select s).ToList(); return View(stk); } if (option == "0" && batch == "" && name != "") { List stk = (from s in db.Stocks where s.Item.Name.StartsWith(""+name+"") select s).ToList(); return View(stk); } return View(db.Stocks.ToList()); } 

Te recomiendo separar las preocupaciones y utilizar un enfoque para que el código en tu controlador sea así, simple, hermoso y extensible:

 public ActionResult Index(ProductSearchModel searchModel) { var business = new ProductBusinessLogic(); var model = business.GetProducts(searchModel); return View(model); } 

Beneficios:

  • Puede poner todo lo que necesita en su ProductSearchModel función de sus requisitos.
  • Puede escribir cualquier lógica en GetProducts según los requisitos. No hay limitación
  • Si agrega un nuevo campo u opción para buscar, su acción y controlador permanecerán intactos.
  • Si la lógica de su búsqueda cambia, su acción y controlador permanecerán intactos.
  • Puede reutilizar la lógica de búsqueda donde sea que necesite buscar productos, en controladores o incluso en otra lógica comercial.
  • Al contar con dicho ProductSearchModel , puede usarlo como modelo de la vista parcial de ProductSearch y puede aplicarle DataAnnotations de datos para mejorar la validación del modelo y ayudar a la IU a renderizarlo usando la Display u otros atributos.
  • Puede agregar otra lógica comercial relacionada con su producto en esa clase lógica de negocios.
  • De esta manera, puede tener una aplicación más organizada.

Implementación de muestra:

Supongamos que tiene una clase de Product :

 public class Product { public int Id { get; set; } public int Price { get; set; } public string Name { get; set; } } 

Puede crear una clase ProductSearchModel y colocar algunos campos sobre los cuales desea buscar:

 public class ProductSearchModel { public int? Id { get; set; } public int? PriceFrom { get; set; } public int? PriceTo { get; set; } public string Name { get; set; } } 

Luego puede poner su lógica de búsqueda en la clase ProductBusinessLogic esta manera:

 public class ProductBusinessLogic { private YourDbContext Context; public ProductBusinessLogic() { Context = new YourDbContext(); } public IQueryable GetProducts(ProductSearchModel searchModel) { var result = Context.Products.AsQueryable(); if (searchModel != null) { if (searchModel.Id.HasValue) result = result.Where(x => x.Id == searchModel.Id); if (!string.IsNullOrEmpty(searchModel.Name)) result = result.Where(x => x.Name.Contains(searchModel.Name)); if (searchModel.PriceFrom.HasValue) result = result.Where(x => x.Price >= searchModel.PriceFrom); if (searchModel.PriceTo.HasValue) result = result.Where(x => x.Price <= searchModel.PriceTo); } return result; } } 

Luego, en su ProductController puede usar de esta manera:

 public ActionResult Index(ProductSearchModel searchModel) { var business = new ProductBusinessLogic(); var model = business.GetProducts(searchModel); return View(model); } 

Nota IMPORTANTE:

En una implementación en el mundo real, considere la implementación de un patrón Dispose adecuado para su clase de negocio para disponer de contexto de base de datos cuando sea necesario. Para obtener más información, consulte Implementación de un método de eliminación o Patrón de eliminación .

Filtrado condicional

.ToList() , .First() , .Count() y algunos otros métodos ejecutan la consulta LINQ final. Pero antes de que se ejecute, puedes aplicar filtros así:

 var stocks = context.Stocks.AsQueryable(); if (batchNumber != null) stocks = stocks.Where(s => s.Number = batchNumber); if (name != null) stocks = stocks.Where(s => s.Name.StartsWith(name)); var result = stocks.ToList(); // execute query 

WhereIf LINQ Extension

Simple WhereIf puede simplificar significativamente el código:

 var result = db.Stocks .WhereIf(batchNumber != null, s => s.Number == batchNumber) .WhereIf(name != null, s => s.Name.StartsWith(name)) .ToList(); 

WhereIf implementation. Es un método de extensión simple para IQueryable :

 public static class CollectionExtensions { public static IQueryable WhereIf( this IQueryable source, bool condition, Func predicate) { if (condition) return source.Where(predicate).AsQueryable(); else return source; } } 

No-SiSi es el modo LINQ (recomendado)

WhereIf proporciona una forma más declarativa, si no desea utilizar extensiones, puede filtrar de la siguiente manera:

 var result = context.Stocks .Where(batchNumber == null || stock.Number == batchNumber) .Where(name == null || s => s.Name.StartsWith(name)) .ToList(); 

Da exactamente el mismo efecto que WhereIf y funcionará más rápido, ya que el tiempo de ejecución necesitará construir solo un ExpressionTree en lugar de crear múltiples árboles y fusionarlos.

 public ActionResult Index(string searchid) { var personTables = db.PersonTables.Where(o => o.Name.StartsWith(searchid) )|| o.CombanyTable.ComName.StartsWith(searchid) ).Include(k => k.CombanyTable); return View(personTables.ToList()); }