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!
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());
}
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:
ProductSearchModel
setzen, je nach Ihren Anforderungen.GetProducts
basierend auf den Anforderungen schreiben. Es gibt keine Einschränkung.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.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 .
.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
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;
}
}
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.
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.
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());
}