Por fin luego de mucho luchar hemos hallado la contestación de este dilema que algunos los lectores de nuestro sitio presentan. Si tienes algún detalle que compartir no dejes de dejar tu conocimiento.
Solución:
Le recomiendo que separe las preocupaciones y utilice un enfoque en el que el código de su 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:
- Puedes poner todo lo que necesites en tu
ProductSearchModel
basado en sus requisitos. - Puedes escribir cualquier lógica en
GetProducts
basado en 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 siempre que necesite buscar en productos, en controladores o incluso en otra lógica empresarial.
- Tener tal
ProductSearchModel
puedes usarlo como modelo deProductSearch
vista parcial y se puede aplicarDataAnnotations
para mejorar la validación del modelo y ayudar a la interfaz de usuario a representarlo usandoDisplay
u otro attributes. - Puede agregar otra lógica empresarial relacionada con su producto en esa clase de lógica empresarial.
- Siguiendo de esta manera podrás tener una aplicación más organizada.
Ejemplo de implementación:
Supongamos que tienes un Product
clase:
public class Product
public int Id get; set;
public int Price get; set;
public string Name get; set;
Puedes crear un ProductSearchModel
clase y coloque algunos campos que desea buscar en función de ellos:
public class ProductSearchModel
public int? Id get; set;
public int? PriceFrom get; set;
public int? PriceTo get; set;
public string Name get; set;
Entonces puedes poner tu lógica de búsqueda en ProductBusinessLogic
clase de 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;
Entonces en tu ProductController
puedes 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 del mundo real, considere implementar un Dispose
patrón para que su clase empresarial elimine el contexto de la base de datos cuando sea necesario. Para obtener más información, consulte Implementación de un método Dispose o Dispose Pattern.
Filtrado condicional
.ToList()
, .First()
, .Count()
y algunos otros métodos ejecutan la consulta LINQ final. Pero antes de que se ejecute, puede 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
Extensión WhereIf LINQ
Sencillo 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();
Implementación WhereIf. Es un método de extensión simple para IQueryable
:
public static class CollectionExtensions
public static IQueryable WhereIf(
this IQueryable source,
bool condition,
Expression> predicate)
if (condition)
return source.Where(predicate);
else
return source;
Modo LINQ no WhereIf (recomendado)
WhereIf
proporciona una forma más declarativa, si no desea usar extensiones, puede filtrar así:
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 construir varios árboles y fusionarlos.
Si estás de acuerdo, tienes la opción de dejar un enunciado acerca de qué le añadirías a este tutorial.