Linq:有条件地在where子句中添加条件

use*_*358 87 linq entity-framework linq-to-sql

我有这样的查询

(from u in DataContext.Users
       where u.Division == strUserDiv 
       && u.Age > 18
       && u.Height > strHeightinFeet  
       select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();
Run Code Online (Sandbox Code Playgroud)

我想根据是否将这些条件提供给运行此查询的方法来添加各种条件,如年龄,高度.所有条件都包括用户部门.如果提供了年龄,我想将其添加到查询中.同样,如果提供了高度,我也想添加它.

如果要使用sql查询完成,我会使用字符串构建器将它们附加到主strSQL查询.但是在Linq中,我只能想到使用IF条件,其中我将编写相同的查询三次,每个IF块都有一个附加条件.有一个更好的方法吗?

谢谢你的时间..

Ree*_*sey 155

如果您没有调用ToList()并且最终映射到DTO类型,则可以随时添加Where子句,并在结尾处构建结果:

var query = from u in DataContext.Users
   where u.Division == strUserDiv 
   && u.Age > 18
   && u.Height > strHeightinFeet
   select u;

if (useAge)
   query = query.Where(u => u.Age > age);

if (useHeight)
   query = query.Where(u => u.Height > strHeightinFeet);

// Build the results at the end
var results = query.Select(u => new DTO_UserMaster
   {
     Prop1 = u.Name,
   }).ToList();
Run Code Online (Sandbox Code Playgroud)

这仍然只会导致对数据库的单次调用,这与在一次传递中编写查询一样有效.

  • 随后的Where条件汇总为OR或AND? (4认同)
  • @ vi100他们将是额外的过滤器,所以AND (4认同)

Mat*_*nes 15

一种选择.

bool? age = null

(from u in DataContext.Users
           where u.Division == strUserDiv 
           && (age == null || (age != null && u.Age > age.Value))
           && u.Height > strHeightinFeet  
           select new DTO_UserMaster
           {
             Prop1 = u.Name,
           }).ToList();
Run Code Online (Sandbox Code Playgroud)

或者您可以切换到linq的方法语法,并使用if条件将表达式附加到where子句.


Yur*_*kiy 13

我通常使用方法链接,但有同样的问题.这是我使用的扩展

public static IQueryable<T> ConditionalWhere<T>(
        this IQueryable<T> source, 
        Func<bool> condition,
        Expression<Func<T, bool>> predicate)
    {
        if (condition())
        {
            return source.Where(predicate);
        }

        return source;
    }
Run Code Online (Sandbox Code Playgroud)

它有助于避免链断裂.也同样ConditionalOrderByConditionalOrderByDescending是有益的.

  • 效果很好!谢谢!我还将*condition*的重载作为一个简单的布尔值而不是函数,以使其更直观,其中委托会增加不必要的复杂性.我现在经常使用这种扩展方法,非常感谢你的解决方案. (4认同)
  • 它应该是这样的: var Fruits = await db.Fruits .ConditionalWhere(() =&gt; color != null, f=&gt; f.Color == color) .ConditionalWhere(() =&gt;成熟 != null, f =&gt; f .成熟 == 成熟) .ToListAsync(); (2认同)

小智 6

只是我在我的 where 子句中使用它作为

    public IList<ent_para> getList(ent_para para){
     db.table1.Where(w=>(para.abc!=""?w.para==para.abc:true==true) && (para.xyz!=""?w.xyz==para.xyz:true==true)).ToList();
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*kel 5

这是我做类似事情的代码。这是我的 WCF SOAP Web 服务 api 上的一个方法。

    public FruitListResponse GetFruits(string color, bool? ripe)
    {
        try
        {
            FruitContext db = new FruitContext();
            var query = db.Fruits.Select(f => f);
            if (color != null)
            {
                query = query.Where(f => f.Color == color);
            }
            if (ripe != null)
            {
                query = query.Where(f => f.Ripe == ripe);
            }
            return new FruitListResponse
            {
                Result = query.Select(f => new Fruit { Id = f.FruitId, Name = f.Name }).ToList()
            };
        }
        catch (Exception e)
        {
            return new FruitListResponse { ErrorMessage = e.Message };
        }
    }
Run Code Online (Sandbox Code Playgroud)

基本查询Select(f => f)意味着基本上一切,并且Where子句可以选择性地附加到它。决赛Select是可选的。我用来将数据库行对象转换为结果“水果”对象。


Mel*_*elu 5

根据特定条件添加 where 条件...

from u in DataContext.Users
where u.Division == strUserDiv 
&& u.Age != null ? u.Age > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
 select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();
Run Code Online (Sandbox Code Playgroud)