使用多个字段过滤/搜索 - ASP.NET MVC

时间:2015-10-15 16:36:19

标签: c# .net asp.net-mvc entity-framework linq

我使用 ASP.NET MVC EF 6

我有一个库存页面,显示库存商品的所有信息。现在我也要过滤记录。

在下图中,我有3个选项。我可以按每个选项进行过滤,一次一个,或者两个或全部三个组合。

我正在考虑为所选的每个选项编写linq查询。但是如果过滤选项增加,这是不可能的。有更好的方法。

谢谢!

enter image description here

这就是我在控制器中所做的事情。(目前下拉列表有两个选项,排除:" - 选择一个 - ")

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());
}

4 个答案:

答案 0 :(得分:69)

我建议你单独关注并使用一种方法,控制器中的代码就像这样,简单,美观和可扩展:

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

<强>优点:

  • 您可以根据自己的要求在ProductSearchModel中填写所需内容。
  • 您可以根据要求在GetProducts中编写任何逻辑。没有限制。
  • 如果您添加新字段或选项进行搜索,您的操作和控制器将保持不变。
  • 如果您的搜索逻辑发生变化,您的操作和控制器将保持不变。
  • 您可以在需要搜索产品,控制器甚至其他业务逻辑的任何地方重复使用搜索逻辑。
  • 拥有此类ProductSearchModel,您可以将其用作ProductSearch部分视图的模型,并且可以对其应用DataAnnotations以增强模型验证并帮助UI使用{{Display进行渲染1}}或其他属性。
  • 您可以在该业务逻辑类中添加与您的产品相关的其他业务逻辑。
  • 按照这种方式,您可以拥有更有条理的应用程序。

示例实施:

假设您有一个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 methodDispose Pattern

答案 1 :(得分:12)

条件过滤

.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 Extension

简单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,
        Func<TSource, bool> 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而不是构建多个树并合并它们。

答案 2 :(得分:0)

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());
}

答案 3 :(得分:0)

我已经编写了一些扩展程序来简化此操作。 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;

基本上,如果条件为true,则初始If()方法将应用传递的if链。 IfChain()是您的嵌套if-else语句。 IfChain()允许您链接多个IfElse(),并以Else()结尾。

如果条件为真,WhereIf()只会有条件地应用where子句。

如果您对库感兴趣,https://github.com/xKloc/LinqConditionalExtensions有自述文件。