条件Linq查询

sgw*_*ill 87 c# linq .net-3.5 linq-to-sql

我们正在研究日志查看器.该用户可以选择按用户,严重程度等进行过滤.在Sql中我会添加到查询字符串,但我想用Linq来做.我怎样才能有条件地添加where-clause?

Dar*_*opp 154

如果您只想过滤某些标准,请执行以下操作

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);
Run Code Online (Sandbox Code Playgroud)

这样做可以使Expression树完全符合您的要求.这样,创建的SQL将完全符合您的需求而且不会少.

  • 嗨你有什么建议使用where子句OR而不是ANDs ..? (2认同)

小智 21

如果需要基于List/Array过滤,请使用以下命令:

    public List<Data> GetData(List<string> Numbers, List<string> Letters)
    {
        if (Numbers == null)
            Numbers = new List<string>();

        if (Letters == null)
            Letters = new List<string>();

        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();

    }
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最好和最正确的答案.条件|| 只比较第一部分并跳过第二部分,如果第一部分是真的...很好地完成! (3认同)
  • 此构造包括生成的 SQL 查询中表达式的“or”部分。接受的答案将生成更有效的陈述。当然,这取决于数据提供商的优化。LINQ-to-SQL 可能有更好的优化,但 LINQ-to-Entities 却没有。 (2认同)

sgw*_*ill 20

我结束使用类似于Daren的答案,但使用了IQueryable接口:

IQueryable<Log> matches = 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();
Run Code Online (Sandbox Code Playgroud)

这会在命中数据库之前构建查询.该命令直到最后的.ToList()才会运行.


Lar*_*lum 14

当涉及到条件linq时,我非常喜欢过滤器和管道模式.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

基本上,您为每个过滤器案例创建一个扩展方法,该过滤器案例包含IQueryable和一个参数.

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这样做:

bool lastNameSearch = true/false; // depending if they want to search by last name,
Run Code Online (Sandbox Code Playgroud)

where声明中有这个:

where (lastNameSearch && name.LastNameSearch == "smith")
Run Code Online (Sandbox Code Playgroud)

意味着在创建最终查询时,如果lastNameSearchfalse查询将完全省略用于姓氏搜索的任何 SQL。


Rya*_*yan 5

我用扩展方法解决了这个问题,该方法允许在流利的表达式中间有条件地启用LINQ。这样就无需用if语句将表达式分开。

.If() 扩展方法:

public static IQueryable<TSource> If<TSource>(
        this IQueryable<TSource> source,
        bool condition,
        Func<IQueryable<TSource>, IQueryable<TSource>> branch)
    {
        return condition ? source : branch(source);
    }
Run Code Online (Sandbox Code Playgroud)

这使您可以执行以下操作:

return context.Logs
     .If(filterBySeverity, q => q.Where(p => p.Severity == severity))
     .If(filterByUser, q => q.Where(p => p.User == user))
     .ToList();
Run Code Online (Sandbox Code Playgroud)

这也是一个IEnumerable<T>可以处理大多数其他LINQ表达式的版本:

public static IEnumerable<TSource> If<TSource>(
    this IEnumerable<TSource> source,
    bool condition,
    Func<IEnumerable<TSource>, IEnumerable<TSource>> branch)
    {
        return condition ? source : branch(source);
    }
Run Code Online (Sandbox Code Playgroud)