[英]Dynamic WHERE clause in LINQ
将动态 WHERE 子句组合到 LINQ 语句的最佳方法是什么?
我在一个表单上有几十个复选框,并将它们作为: Dictionary<string, List<string>> (Dictionary<fieldName,List<values>>) 传递给我的 LINQ 查询。
public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
var q = from c in db.ProductDetail
where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
// insert dynamic filter here
orderby c.ProductTypeName
select c;
return q;
}
我有类似的场景,我需要根据用户输入添加过滤器并链接 where 子句。
这是示例代码。
var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);
您还可以使用 LinqKit 中的 PredicateBuilder 使用 Or 或 And 链接多个类型安全的 lambda 表达式。
如果您的列是简单类型(如字符串),则可以采用一种简单的方法
public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
{
return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
}
使用三元运算符动态决定是否包含条件似乎要简单得多
列出 productList = new List();
productList =
db.ProductDetail.Where(p => p.ProductDetailID > 0 //Example prop
&& (String.IsNullOrEmpty(iproductGroupName) ? (true):(p.iproductGroupName.Equals(iproductGroupName)) ) //use ternary operator to make the condition dynamic
&& (ID == 0 ? (true) : (p.ID == IDParam))
).ToList();
我想出了一个即使我也能理解的解决方案……通过使用“包含”方法,您可以链接任意数量的 WHERE。 如果 WHERE 是一个空字符串,它将被忽略(或评估为全选)。 这是我在 LINQ 中连接 2 个表、应用多个 where 子句并填充要返回到视图的模型类的示例。 (这是全选)。
public ActionResult Index()
{
string AssetGroupCode = "";
string StatusCode = "";
string SearchString = "";
var mdl = from a in _db.Assets
join t in _db.Tags on a.ASSETID equals t.ASSETID
where a.ASSETGROUPCODE.Contains(AssetGroupCode)
&& a.STATUSCODE.Contains(StatusCode)
&& (
a.PO.Contains(SearchString)
|| a.MODEL.Contains(SearchString)
|| a.USERNAME.Contains(SearchString)
|| a.LOCATION.Contains(SearchString)
|| t.TAGNUMBER.Contains(SearchString)
|| t.SERIALNUMBER.Contains(SearchString)
)
select new AssetListView
{
AssetId = a.ASSETID,
TagId = t.TAGID,
PO = a.PO,
Model = a.MODEL,
UserName = a.USERNAME,
Location = a.LOCATION,
Tag = t.TAGNUMBER,
SerialNum = t.SERIALNUMBER
};
return View(mdl);
}
我有同样的问题( 用户定义的linq过滤器 ),@ tvanfosson告诉我有关Dynamic Linq( http://code.msdn.microsoft.com/csharpsamples )的信息。
您可以使用 Any() 扩展方法。 以下似乎对我有用。
XStreamingElement root = new XStreamingElement("Results",
from el in StreamProductItem(file)
where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
);
Console.WriteLine(root.ToString());
其中 'fieldsToSearch' 和 'fieldsToReturn' 都是 List 对象。
System.Linq.Dynamic可能会帮助您在运行时构建 LINQ 表达式。
- 动态查询库依赖于一种简单的表达式语言,用于在字符串中制定表达式和查询。
- 它为您提供了基于字符串的扩展方法,您可以将任何字符串表达式传递到其中,而不是使用语言运算符或类型安全的 lambda 扩展方法。
- 它简单易用,并且在查询完全是动态的并且您希望提供最终用户 UI 来帮助构建它们的场景中特别有用。
资料来源:动态 LINQ 概述
该库允许您从纯字符串创建 LINQ 表达式,因此,您可以根据需要动态构建连接字符串的 LINQ 表达式。
以下是可以实现的示例:
var resultDynamic = context.Customers
.Where("City == @0 and Age > @1", "Paris", 50)
.ToList();
如果有人感兴趣,这是我提出的解决方案。
https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/
首先我们确定我们需要使用的单个元素类型(Of TRow As DataRow),然后确定我们正在使用的“源”并将标识符与该源绑定((source As TypedTableBase(Of TRow))。然后我们必须指定谓词,或将要传递的 WHERE 子句(谓词 As Func(Of TRow, Boolean)),它将返回为 true 或 false。然后我们确定我们希望返回的信息如何排序(OrderByField As String)。我们的然后函数将返回一个 EnumerableRowCollection(Of TRow),我们的数据行集合满足我们的谓词(EnumerableRowCollection(Of TRow)) 的条件。这是一个基本示例。当然你必须确保你的订单字段不包含nulls,或者已经正确处理了这种情况并确保您的列名(如果您使用的是强类型数据源,请不要介意这一点,它会为您重命名列)是标准的。
只是为了分享我对这个案例的想法。
解决方案的另一种方法是:
public IOrderedQueryable GetProductList(string productGroupName, string productTypeName, Dictionary> filterDictionary)
{
return db.ProductDetail
.where
(
p =>
(
(String.IsNullOrEmpty(productGroupName) || c.ProductGroupName.Contains(productGroupName))
&& (String.IsNullOrEmpty(productTypeName) || c.ProductTypeName.Contains(productTypeName))
// Apply similar logic to filterDictionary parameter here !!!
)
);
}
这种方法非常灵活,允许任何参数都可以为空。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.