it-swarm.com.de

Filtern/Suchen mit mehreren Feldern - ASP.NET MVC

Ich verwende ASP.NET MVC mit EF 6.

Ich habe eine Lagerseite, auf der alle Informationen zu Lagerbeständen angezeigt werden. Jetzt möchte ich auch Datensätze filtern.

Im Bild unten habe ich 3 Optionen. Ich könnte nach jeder Option filtern, eine nach der anderen oder eine Kombination aus zwei oder mit allen drei. 

Ich dachte daran, für jede ausgewählte Option eine linq-Abfrage zu schreiben. Dies wäre jedoch nicht möglich, wenn die Filteroption erhöht wird. Gibt es einen besseren Weg dazu? 

Vielen Dank!

 enter image description here

Dies ist, was ich in meinem Controller gemacht habe (derzeit hat Dropdown zwei Optionen, außer: "- 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());
}
31
Avi-B

Ich empfehle Ihnen, getrennte Anliegen zu verwenden und den Ansatz zu verwenden, dass der Code in Ihrem Controller so, einfach, schön und erweiterbar ist:

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

Leistungen:

  • Sie können alles, was Sie brauchen, in Ihre ProductSearchModel setzen, je nach Ihren Anforderungen.
  • Sie können eine beliebige Logik in GetProducts basierend auf den Anforderungen schreiben. Es gibt keine Einschränkung.
  • Wenn Sie ein neues Feld oder eine neue Option zur Suche hinzufügen, bleiben Ihre Aktion und Ihr Controller unberührt.
  • Wenn sich die Logik Ihrer Suche ändert, bleiben Ihre Aktion und Ihr Controller unberührt.
  • Sie können die Suchlogik überall dort verwenden, wo Sie nach Produkten, Steuerungen oder sogar in anderen Geschäftslogiken suchen müssen.
  • Mit dieser ProductSearchModel können Sie es als Modell für die ProductSearch-Teilansicht verwenden und DataAnnotations anwenden, um die Modellvalidierung zu verbessern und der Benutzeroberfläche zu helfen, sie mithilfe von Display oder anderen Attributen wiederzugeben.
  • Sie können andere Geschäftslogik, die sich auf Ihr Produkt bezieht, in dieser Geschäftslogikklasse hinzufügen.
  • Auf diese Weise können Sie eine besser organisierte Anwendung haben.

Beispielimplementierung:

Angenommen, Sie haben eine Product-Klasse:

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

Sie können eine ProductSearchModel-Klasse erstellen und einige Felder eingeben, die Sie basierend darauf durchsuchen möchten:

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

Dann können Sie Ihre Suchlogik in der Klasse ProductBusinessLogic folgendermaßen eingeben:

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

Dann können Sie in Ihrer ProductController diesen Weg verwenden:

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

Wichtige Notiz:

Erwägen Sie in einer realen Implementierung die Implementierung eines geeigneten Dispose-Musters für Ihre Business-Klasse, um bei Bedarf den Db-Kontext zur Verfügung zu stellen. Weitere Informationen finden Sie unter Implementieren einer Dispose-Methode oder Dispose Pattern .

67
Reza Aghaei

Bedingte Filterung

.ToList(), .First(), .Count() und einige andere Methoden führen die letzte LINQ-Abfrage aus. Aber bevor es ausgeführt wird, können Sie einfach Filter anwenden:

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-Erweiterung

Einfache WhereIf kann den Code erheblich vereinfachen:

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

WhereIf Implementierung. Es ist eine einfache Erweiterungsmethode für 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;
    }
}

Nicht-WhereIf-LINQ-Methode (empfohlen)

WhereIf bietet mehr deklarative Möglichkeiten. Wenn Sie keine Erweiterungen verwenden möchten, können Sie einfach so filtern:

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

Es hat genau denselben Effekt wie WhereIf und wird schneller arbeiten, da zur Laufzeit nur ein ExpressionTree erstellt werden muss, anstatt mehrere Bäume zu erstellen und diese zusammenzuführen.

12
Andrei

Ich habe einige Erweiterungen geschrieben, um das zu erleichtern. https://www.nuget.org/packages/LinqConditionalExtensions/

Das Rad wird nicht neu erfunden. Einige Erweiterungen wurden bereits empfohlen. Sie können Ihre Logik wie folgt umschreiben.

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;

Grundsätzlich wendet die If()-Methode die übergebene If-Kette an, wenn die Bedingung erfüllt ist. Die IfChain() ist Ihre verschachtelte if-else-Anweisung. Mit IfChain() können Sie mehrere IfElse() verketten und mit einer Else() beenden.

Die WhereIf() wird Ihre where-Klausel nur bedingt anwenden, wenn die Bedingung erfüllt ist.

Wenn Sie sich für die Bibliothek interessieren, hat https://github.com/xKloc/LinqConditionalExtensions eine Readme-Datei.

0
Todd Skelton
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());
}
0
ana