是否可以将LINQ WHERE与条件布尔值一起使用,如果为false,则跳过。我的代码示例如下:-
var filters = ListResponse.filter.Where(a => a.FLRefID == EvtID).ToList();
foreach(var tofilter in filters)
{
if (tofilter == null)
continue;
// The value in tofilter can be empty
bool bFilterID = string.IsNullOrEmpty(tofilter.FLEventID);
bool bFilterText = string.IsNullOrEmpty(tofilter.FLText);
bool bFilterSource = string.IsNullOrEmpty(tofilter.FLSource);
bool bFilterLevel = string.IsNullOrEmpty(tofilter.FLLevel);
// Here in LINQ where I want to filter
// EventDetails is List of Event Viewer Collection.
var logs = EventDetails.Where(ax => bFilterID ? (ax.EventID == tofilter.FLEventID) | bFilterText ? (ax.EventMessage.Contains(tofilter.FLText)) | bFilterSource ? (ax.EventSourceName == tofilter.FLSource) | bFilterLevel ? (ax.Level == tofilter.FLLevel));
string json = JsonConvert.SerializeObject(logs);
}
比方说,USER选择了他们要过滤的ID=1, SourceName=Application
,其余的为空。如果使用bFilterID = true
,然后使用ax.EventID == tofilter.FLEventID
,如何在LINQ中添加条件。如果为False(用户未设置),它将跳过条件。过滤器可以是动态的,但必须至少有1个条件才能由USER设置。
我实际上不确定我要搜索的内容有哪些关键字,因为我不知道它是否存在。
更新: 我有Mik的测试答案,也有npo的答案。
> 18-03-2019 10:30:17.876405 [INFO] Time taken NPO 1: 00:00:00.0705490
> 18-03-2019 10:30:17.889374 [INFO] Time taken NPO 2: 00:00:00.0123487
> 18-03-2019 10:30:17.903334 [INFO] Time taken MIK: 00:00:00.0146780
>
> 18-03-2019 10:30:17.947219 [INFO] Time taken NPO 1: 00:00:00.0435493
> 18-03-2019 10:30:17.977139 [INFO] Time taken NPO 2: 00:00:00.0297257
> 18-03-2019 10:30:17.981127 [INFO] Time taken MIK: 00:00:00.0036274
>
> 18-03-2019 10:30:28.536724 [INFO] Time taken NPO 1: 00:00:00.2011405
> 18-03-2019 10:30:28.596560 [INFO] Time taken NPO 2: 00:00:00.0594285
> 18-03-2019 10:30:28.634464 [INFO] Time taken MIK: 00:00:00.0376055
答案 0 :(得分:6)
这就是我的做法:
IQueryable<EventDetails> res = EventDetails;
if( !string.IsNullOrEmpty(tofilter.FLEventID) )
res = res.Where(ax => ax.EventID == tofilter.FLEventID);
if( !string.IsNullOrEmpty(tofilter.FLText) )
res = res.Where(ax => ax.EventMessage.Contains(tofilter.FLText));
if( !string.IsNullOrEmpty(tofilter.FLSource) )
res = res.Where(ax => ax.EventSourceName == tofilter.FLSource);
if( !string.IsNullOrEmpty(tofilter.FLLevel) )
res = res.Where(ax => ax.Level == tofilter.FLLevel);
string json = JsonConvert.SerializeObject(res);
它会生成多个子查询,但是我不认为存在性能问题,并且可读性更高。
顺便说一句,我颠倒了您的IsNullOrEmpty
测试,因为在您的代码中,您仅对空字符串进行过滤...
答案 1 :(得分:2)
您可以编写扩展方法来有条件地应用过滤器:
new Chart(document.getElementById("radar-chart"), {
type: 'radar',
data: {
labels: ["SQL", "CSS", "HTML"],
datasets: [
{
label: "Scripting",
fill: true,
backgroundColor: "rgba(255,215,0,0.2)",
borderColor: "rgba(255,215,0,1)",
pointBorderColor: "#ffe100",
pointBackgroundColor: "rgba(255,215,0,1)",
data: [7.77,8.2,6.5]
},
]
},
options: {
title: {
display: true,
text: 'Scripting skill'
}
}
});
您的查询将变为:
public static IQueryable<T> WhereIf<T>(
this IQueryable<T> source, bool condition,
Expression<Func<T, bool>> predicate)
{
return condition ? source.Where(predicate) : source;
}
答案 2 :(得分:1)
尝试一下
var filters = ListResponse.filter.Where(a => a.FLRefID == EvtID).ToList();
foreach(var tofilter in filters)
{
if (tofilter == null)
continue;
// The value in tofilter can be empty
bool bFilterID = string.IsNullOrEmpty(tofilter.FLEventID);
bool bFilterText = string.IsNullOrEmpty(tofilter.FLText);
bool bFilterSource = string.IsNullOrEmpty(tofilter.FLSource);
bool bFilterLevel = string.IsNullOrEmpty(tofilter.FLLevel);
if(new bool[]{bFilterID, bFilterText, bFilterSource, bFilterLevel}.All(z=>!z)) continue // continue when no filters were set like you wanted
var logs = EventDetails.Where(ax => (bFilterID ? (ax.EventID == tofilter.FLEventID) : true ) || (bFilterText ? (ax.EventMessage.Contains(tofilter.FLText): true) || (bFilterSource ? (ax.EventSourceName == tofilter.FLSource) : true) || (bFilterLevel ? (ax.Level == tofilter.FLLevel) : true));
string json = JsonConvert.SerializeObject(logs);
}
但是对于这种情况,最好使用谓词
这里是一个例子:
谓词构建器只是构建谓词的助手 可以在这里找到:Predicates
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T> () { return f => true; }
public static Expression<Func<T, bool>> False<T> () { return f => false; }
public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
}
针对您的情况,您可以执行以下操作
var filters = ListResponse.filter.Where(a => a.FLRefID == EvtID).ToList();
foreach(var tofilter in filters)
{
if (tofilter == null)
continue;
// The value in tofilter can be empty
bool bFilterID = string.IsNullOrEmpty(tofilter.FLEventID);
bool bFilterText = string.IsNullOrEmpty(tofilter.FLText);
bool bFilterSource = string.IsNullOrEmpty(tofilter.FLSource);
bool bFilterLevel = string.IsNullOrEmpty(tofilter.FLLevel);
if(new bool[]{bFilterID, bFilterText, bFilterSource, bFilterLevel}.All(z=>!z)) continue // continue when no filters were set like you wanted
var predicate = PredicateBuilder.False<EventDetails> ();
if(bFilterID) predicate= predicate.Or(ax => ax.EventID == tofilter.FLEventID);
if(bFilterText) predicate= predicate.Or(ax => ax.EventMessage.Contains(tofilter.FLText));
if(bFilterSource) predicate= predicate.Or(ax => ax.EventSourceName == tofilter.FLSource);
if(bFilterLevel) predicate= predicate.Or(ax => ax.Level == tofilter.FLLevel);
var logs = EventDetails.Where(predicate.Compile());
string json = JsonConvert.SerializeObject(logs);
}