我们正在研究日志查看器.该用户可以选择按用户,严重程度等进行过滤.在Sql中我会添加到查询字符串,但我想用Linq来做.我怎样才能有条件地添加where-clause?
如果您只想过滤某些标准,请执行以下操作
var logs = from log in context.Logs select log; if (filterBySeverity) logs = logs.Where(p => p.Severity == severity); if (filterByUser) logs = logs.Where(p => p.User == user);
这样做可以使Expression树完全符合您的要求.这样,创建的SQL将完全符合您的需求而且不会少.
如果需要基于List/Array过滤,请使用以下命令:
public List GetData(ListNumbers, List Letters) { if (Numbers == null) Numbers = new List (); if (Letters == null) Letters = new List (); var q = from d in database.table where (Numbers.Count == 0 || Numbers.Contains(d.Number)) where (Letters.Count == 0 || Letters.Contains(d.Letter)) select new Data { Number = d.Number, Letter = d.Letter, }; return q.ToList(); }
我结束使用类似于Daren的答案,但使用了IQueryable接口:
IQueryablematches = m_Locator.Logs; // Users filter if (usersFilter) matches = matches.Where(l => l.UserName == comboBoxUsers.Text); // Severity filter if (severityFilter) matches = matches.Where(l => l.Severity == comboBoxSeverity.Text); Logs = (from log in matches orderby log.EventTime descending select log).ToList();
这会在命中数据库之前构建查询.该命令直到最后的.ToList()才会运行.
当涉及到条件linq时,我非常喜欢过滤器和管道模式.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/
基本上,您为每个过滤器案例创建一个扩展方法,该过滤器案例包含IQueryable和一个参数.
public static IQueryableHasID(this IQueryable query, long? id) { return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query; }
我用扩展方法解决了这个问题,该方法允许在流利的表达式中间有条件地启用LINQ。这样就无需用if
语句将表达式分开。
.If()
扩展方法:
public static IQueryableIf ( this IQueryable source, bool condition, Func , IQueryable > branch) { return condition ? source : branch(source); }
这使您可以执行以下操作:
return context.Logs .If(filterBySeverity, q => q.Where(p => p.Severity == severity)) .If(filterByUser, q => q.Where(p => p.User == user)) .ToList();
这也是一个IEnumerable
可以处理大多数其他LINQ表达式的版本:
public static IEnumerableIf ( this IEnumerable source, bool condition, Func , IEnumerable > branch) { return condition ? source : branch(source); }