使用多个字段过滤/搜索 - ASP.NET MVC
Posted
技术标签:
【中文标题】使用多个字段过滤/搜索 - ASP.NET MVC【英文标题】:Filter/Search using Multiple Fields - ASP.NET MVC 【发布时间】:2015-10-15 16:36:18 【问题描述】:我正在使用 ASP.NET MVC 和 EF 6。
我有一个股票页面,其中显示了有关股票项目的所有信息。现在我也想过滤记录。
在下图中,我有 3 个选项。我可能会按每个选项进行过滤,一次一个或两个或三个的组合。
我正在考虑为每个选择的选项编写 linq 查询。但是如果过滤器选项增加,这将是不可能的。有没有更好的方法。
谢谢!
这是我在控制器中所做的。(当前下拉菜单有两个选项,不包括:“-- select one--”)
public ActionResult StockLevel(string option, string batch, string name)
if (option != "0" && batch == "" && name == "")
if(option == "BelowMin")
List<Stock> stk = (from s in db.Stocks
where s.Qty < s.Item.AlertQty
select s).ToList();
return View(stk);
else
List<Stock> stk = (from s in db.Stocks
where s.Qty == s.InitialQty
select s).ToList();
return View(stk);
if (option == "0" && batch != "" && name == "")
List<Stock> stk = (from s in db.Stocks
where s.BatchNo == batch
select s).ToList();
return View(stk);
if (option == "0" && batch == "" && name != "")
List<Stock> stk = (from s in db.Stocks
where s.Item.Name.StartsWith(""+name+"")
select s).ToList();
return View(stk);
return View(db.Stocks.ToList());
【问题讨论】:
您是否已经尝试过任何代码? 是的,刚刚为这三个选项中的每一个都写了查询。但我没有写多个选项,因为我认为这不是好方法。 @Avi-B 我建议在这种情况下使用SearchModel
,如果您对这种方法感兴趣,请告诉我,我会为您发布答案。
您可以使用谓词,但在这种情况下,最好的办法是使用表达式树在填写表单元素时动态创建搜索查询。
使用 !string.IsNullOrWhiteSpace(batch) 而不是 batch == ""
【参考方案1】:
我建议您分离关注点并使用一种方法,使您的控制器中的代码像这样简单、美观且可扩展:
public ActionResult Index(ProductSearchModel searchModel)
var business = new ProductBusinessLogic();
var model = business.GetProducts(searchModel);
return View(model);
好处:
您可以根据自己的要求在ProductSearchModel
中添加您需要的任何内容。
您可以根据需要在GetProducts
中编写任何逻辑。没有限制。
如果您添加新字段或选项进行搜索,您的操作和控制器将保持不变。
如果您的搜索逻辑发生变化,您的操作和控制器将保持不变。
您可以在需要搜索产品、控制器甚至其他业务逻辑的任何地方重复使用搜索逻辑。
拥有这样的ProductSearchModel
,您可以将其用作ProductSearch
局部视图的模型,您可以对其应用DataAnnotations
以增强模型验证并帮助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<Product> 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
模式,以便在需要时处理数据库上下文。如需更多信息,请查看Implementing a Dispose method 或Dispose Pattern。
【讨论】:
我正在使用您的想法,并且在我搜索时效果很好,但是当我尝试对数据进行排序时,搜索条件丢失了。我的操作看起来像这样public ActionResult Index(string sortOrder, SearchTransacModel searchModel, SearchTransacModel currentFilter, int? page)
我将搜索模型传递给这样的视图,以保留我的搜索参数`ViewBag.currentFilter = searchModel;`
GetProducts
方法的结果是IQueryable<Product>
,您可以简单地对结果应用排序和分页。将合适的排序列名称、排序顺序和页码传递给操作并使用它们就足够了。
在渲染分页链接和负责排序的列标题时,您应该在链接中添加合适的查询字符串以正确操作。在我的项目中,这是我的Grid
helper/component 的责任。
@KayGee 最好在这篇文章的启发下提出一个新问题,让社区帮助你。另外,如果您通知我,我当然也会看看您的问题:)
ModelBinder
查看动作参数,因为它看到动作有一个ProductSearchModel
类型的参数,所以创建它的一个实例。然后查看查询字符串或表单参数,检查是否为Id
属性(不区分大小写)发布了值,然后初始化对象的Id
属性,Name
属性和其他属性相同。如需更多信息,请搜索ASP.NET MVC 中的模型绑定,并阅读this one 等几篇文章。【参考方案2】:
条件过滤
.ToList()
、.First()
、.Count()
和其他一些方法执行最终的 LINQ 查询。但在执行之前,您可以像这样应用过滤器:
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 扩展
简单的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<TSource> WhereIf<TSource>(
this IQueryable<TSource> source,
bool condition,
Expression<Func<TSource, bool>> predicate)
if (condition)
return source.Where(predicate);
else
return source;
Non-WhereIf LINQ 方式(推荐)
WhereIf
提供了更多的声明方式,如果你不想使用扩展,你可以像这样过滤:
var result = context.Stocks
.Where(batchNumber == null || stock.Number == batchNumber)
.Where(name == null || s => s.Name.StartsWith(name))
.ToList();
它提供与WhereIf
完全相同的效果,并且运行速度更快,因为运行时只需构建一个 ExpressionTree,而不是构建多个树并合并它们。
【讨论】:
好吧,我对 asp.net mvc 和边做边学真的很陌生。我会看一下 int 表达式,看看它是否适合我。谢谢。 使用 WhereIf 的好方法 在 BaseController 中使用它我需要在返回源添加 .AsQueryable.Where(predicate).AsQueryable(); 您推荐的 Non-WhereIf LINQ 方式不是很好!问题是,如果您在数据库上使用它,则会在 SQL 查询中生成空检查。 谓词在扩展方法中应该是 Expression我编写了一些扩展来简化此操作。 https://www.nuget.org/packages/LinqConditionalExtensions/
这不是重新发明***。一些扩展已经被推荐。你可以重写你的逻辑如下。
var results = db.Stocks
.If(option != "0", stocks => stocks
.IfChain(option == "BelowMin", optionStocks => optionStocks
.Where(stock => stock.Qty < stock.Item.AlertQty))
.Else(optionStocks => optionStocks
.Where(stock => stock.Qty == stock.InitialQty)))
.WhereIf(!string.IsNullOrWhiteSpace(batch), stock => stock.BatchNo == batch)
.WhereIf(!string.IsNullOrWhiteSpace(name), stock => stock.Item.Name.StartsWith("" + name + ""))
.ToList();
return results;
基本上,如果条件为真,初始 If()
方法将应用传递的 if 链。 IfChain()
是您的嵌套 if-else 语句。 IfChain()
允许您链接多个 IfElse()
并以 Else()
结尾。
如果条件为真,WhereIf()
只会有条件地应用您的 where 子句。
如果您对该库感兴趣,https://github.com/xKloc/LinqConditionalExtensions 有自述文件。
【讨论】:
【参考方案4】: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());
【讨论】:
添加解决方案的描述。以上是关于使用多个字段过滤/搜索 - ASP.NET MVC的主要内容,如果未能解决你的问题,请参考以下文章
使用 C# 在 ASP.NET MVC 中使用多个参数过滤数据