使用多个字段过滤/搜索 – ASP.NET MVC
我在EF 6中使用ASP.NET MVC 。
我有一个库存页面,显示库存商品的所有信息。 现在我想过滤记录。
在下图中我有3个选项。 我可以按每个选项进行过滤,一次一个,或者两个或全部三个组合。
我正在考虑为所选的每个选项编写linq查询。 但是如果filter选项增加,这将是不可能的。有更好的方法。
谢谢!
这就是我在我的控制器中所做的。(目前下拉有两个选项,不包括:“ – 选择一个 – ”)
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()); }
我建议你单独关注并使用一种方法,控制器中的代码就像这样,简单,美观和可扩展:
public ActionResult Index(ProductSearchModel searchModel) { var business = new ProductBusinessLogic(); var model = business.GetProducts(searchModel); return View(model); }
优点:
- 您可以根据自己的要求在
ProductSearchModel
所需内容。 - 您可以根据需求在
GetProducts
编写任何逻辑。 没有限制。 - 如果添加新字段或选项进行搜索,则操作和控制器将保持不变。
- 如果搜索逻辑发生变化,您的操作和控制器将保持不变。
- 您可以在需要的任何地方重用搜索逻辑来搜索产品,控制器甚至其他业务逻辑。
- 拥有这样的
ProductSearchModel
,您可以将其用作ProductSearch
局部视图的模型,并且可以将DataAnnotations
应用于它以增强模型validation并帮助UI使用Display
或其他属性呈现它。 - 您可以在该业务逻辑类中添加与产品相关的其他业务逻辑。
- 按照这种方式,您可以拥有更有条理的应用程序。
示例实施:
假设您有一个Product
类:
public class Product { public int Id { get; set; } public int Price { get; set; } public string Name { get; set; } }
您可以创建ProductSearchModel
类并根据它们放置要搜索的字段:
public class ProductSearchModel { public int? Id { get; set; } public int? PriceFrom { get; set; } public int? PriceTo { get; set; } public string Name { get; set; } }
然后,您可以通过以下方式将搜索逻辑放在ProductBusinessLogic
类中:
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; } }
然后在您的ProductController
您可以使用以下方式:
public ActionResult Index(ProductSearchModel searchModel) { var business = new ProductBusinessLogic(); var model = business.GetProducts(searchModel); return View(model); }
重要的提示:
在实际的实现中,请考虑为您的业务类实现合适的Dispose
模式,以便在需要时配置db上下文。 有关更多信息,请参阅实现Dispose方法或Dispose Pattern 。
条件过滤
.ToList()
.Count()
和其他一些方法执行最后的LINQ查询。 但在执行之前,您可以像这样应用filter:
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
其中LINQ扩展
简单WhereIf
可以显着简化代码:
var result = db.Stocks .WhereIf(batchNumber != null, s => s.Number == batchNumber) .WhereIf(name != null, s => s.Name.StartsWith(name)) .ToList();
WhereIf实施。 这是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; } }
非WhereIf LINQ方式(推荐)
WhereIf
提供了更多的声明方式,如果你不想使用扩展,你可以像这样过滤:
var result = context.Stocks .Where(batchNumber == null || stock.Number == batchNumber) .Where(name == null || s => s.Name.StartsWith(name)) .ToList();
它提供了与WhereIf
完全相同的效果,并且它将更快地工作,因为运行时只需构建一个ExpressionTree而不是构建多个树并合并它们。
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()); }