将动态WHERE子句组装到LINQ语句的最佳方法是什么?
我在表单上有几十个复选框,并将它们传回:Dictionary< string,List< string>> (字典< 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;
}
答案 0 :(得分:52)
答案 1 :(得分:13)
您还可以使用LinqKit中的PredicateBuilder使用Or或And链接多个类型安全的lambda表达式。
答案 2 :(得分:9)
我有类似的情况,我需要根据用户输入添加过滤器,并链接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);
答案 3 :(得分:8)
如果您的列是像String
这样的简单类型,则可以使用简单的方法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); });
}
答案 4 :(得分:5)
我提出了一个解决方案,即使我能理解......通过使用'Contains'方法,您可以链接尽可能多的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);
}
答案 5 :(得分:2)
我有同样的问题(User defined filter for linq),而@tvanfosson告诉我有关Dynamic Linq(http://code.msdn.microsoft.com/csharpsamples)的信息。
答案 6 :(得分:1)
您可以使用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对象。
答案 7 :(得分:1)
CodePlex上的这个项目有你想要的。
System.Linq.Dynamic - http://dynamiclinq.codeplex.com/
项目说明
扩展System.Linq.Dynamic以支持对实体框架或任何支持IQueryable的提供程序执行字符串中定义的Lambda表达式。
因为它是您可以在Scott Guthrie's Blog找到的源代码的扩展,它允许您执行以下操作:
这样的事情:
答案 8 :(得分:1)
如果有人有兴趣,这是我提出的解决方案。
https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/
首先我们确定我们需要使用的单个元素类型(Of TRow As DataRow),然后识别我们正在使用的“源”并将标识符绑定到该源((源为TypedTableBase(Of TRow))。然后我们必须指定谓词,或者要传递的WHERE子句(谓词As Func(Of TRow,Boolean)),它将返回true或false。然后我们确定我们希望如何排序返回的信息(OrderByField As String然后我们的函数将返回一个EnumerableRowCollection(Of TRow),我们的数据行集合已满足我们谓词的条件(EnumerableRowCollection(Of TRow))。这是一个基本的例子。当然你必须确保你的订单字段没有不包含空值,或已经正确处理了这种情况,并确保您的列名称(如果您使用的是强类型数据源,请不要介意它,它会为您重命名列)是标准的。
答案 9 :(得分:1)
使用三元运算符动态决定是否包含条件似乎越来越简单
列出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();
答案 10 :(得分:1)
只想分享我对此案的想法。
解决方案的另一种方法是:
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 !!!
)
);
}
这种方法非常灵活,并且允许任何参数为空。