有条件的LINQ查询有条件的LINQ查询(Conditional Linq Queries)

2019-06-12 06:59发布

我们正在努力日志查看器。 使用将有用户,严重程度等来过滤在SQL几天我想补充的查询字符串的选项,但我想使用LINQ来做到这一点。 我如何能有条件地加入其中从句?

Answer 1:

如果你想,如果某些条件被传递到只能过滤,做这样的事情

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

否则,这样可以让你的表达树是你想要什么。 在SQL创建这样会正是你需要的也不少。



Answer 2:

如果你需要在一个列表过滤器底座/阵列使用以下命令:

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

    }


Answer 3:

我最终使用类似于达人的答案,但有一个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();

这构建了进入数据库之前查询。 该命令将不会在年底运行,直到.ToList()。



Answer 4:

当涉及到有条件的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;
}


Answer 5:

另一种选择是使用类似讨论的PredicateBuilder 这里 。 它可以让你写,如下面的代码:

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                  .And (Product.IsSelling());

var query = from p in Data.Products.Where (newKids.Or (classics))
            select p;

请注意,我只带了这使用LINQ 2 SQL工作。 的EntityFramework没有实现Expression.Invoke,这对于这种方法的工作是必需的。 我有一个关于这个问题,一个问题在这里 。



Answer 6:

这样做:

bool lastNameSearch = true/false; // depending if they want to search by last name,

在具有这种where语句:

where (lastNameSearch && name.LastNameSearch == "smith")

意味着当创建最终的查询时,如果lastNameSearchfalse查询将完全省略为姓的搜索条件的SQL。



Answer 7:

我解决了这个与扩展方法,以允许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);
    }

这可以让你做到这一点:

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

这里也是一个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);
    }


Answer 8:

这是不是最漂亮的事情,但你可以使用lambda表达式,并选择通过您的条件。 在TSQL我做了很多的下面,使参数可选的:

WHERE字段= @FieldVar OR @FieldVar IS NULL

您可以复制同样的风格,配有下列拉姆达(检查认证为例):

MyDataContext分贝=新MyDataContext();

无效RunQuery(字符串参数1,字符串参数2,INT?参数3){

FUNC checkUser =用户=>

((param1.Length> 0)user.Param1 ==参数1:1 == 1)&&

((param2.Length> 0)user.Param2 == param2的:1 == 1)&&

((参数3 = NULL)user.Param3 ==参数3:?1 == 1);

用户foundUser = db.Users.SingleOrDefault(checkUser);

}



Answer 9:

我最近也有类似的需求,并最终发现了这个在他MSDN。 CSHARP样本的Visual Studio 2008

包括下载的DynamicQuery样品中的类允许你创建在下面的格式运行时动态查询:

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");

使用这个你可以在运行时动态生成一个查询字符串,并将它传递到哪里()方法:

string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; 
var q = from c in db.Customers.Where(queryString, null)
        orderby c.CompanyName
        select c;


Answer 10:

只要使用C#的&&操作:

var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")

编辑:嗯,需要更仔细地阅读。 你想知道如何有条件地添加附加条款。 在这种情况下,我不知道。 :)什么我可能做的就是准备多个查询,并执行正确的,这取决于我最终需要。



Answer 11:

你可以使用一个外部的方法:

var results =
    from rec in GetSomeRecs()
    where ConditionalCheck(rec)
    select rec;

...

bool ConditionalCheck( typeofRec input ) {
    ...
}

这会工作,但不能被分解成表达式树,这意味着LINQ到SQL将运行对每个记录的校验码。

或者:

var results =
    from rec in GetSomeRecs()
    where 
        (!filterBySeverity || rec.Severity == severity) &&
        (!filterByUser|| rec.User == user)
    select rec;

这可能在表达式目录树工作,这意味着LINQ到SQL会进行优化。



Answer 12:

那么,我以为是你可以把过滤条件变成谓词的泛型列表:

    var list = new List<string> { "me", "you", "meyou", "mow" };

    var predicates = new List<Predicate<string>>();

    predicates.Add(i => i.Contains("me"));
    predicates.Add(i => i.EndsWith("w"));

    var results = new List<string>();

    foreach (var p in predicates)
        results.AddRange(from i in list where p.Invoke(i) select i);               

这导致含有“我”,“meyou”列表,“割”。

你可以做与谓词的foreach在一个完全不同的函数,手术室所有谓词优化这一点。



Answer 13:

您可以创建和使用这个扩展方法

public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool isToExecute, Expression<Func<TSource, bool>> predicate)
{
    return isToExecute ? source.Where(predicate) : source;
}


文章来源: Conditional Linq Queries