Linq:有条件地向where子句添加条件

时间:2012-06-04 16:24:12

标签: 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();

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

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

谢谢你的时间..

9 个答案:

答案 0 :(得分:142)

如果您没有调用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();

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

答案 1 :(得分:14)

一个选项。

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

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

答案 2 :(得分:11)

我通常使用方法链接但遇到同样的问题。这是我使用的扩展

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

有助于避免链断裂。同样ConditionalOrderByConditionalOrderByDescending也很有帮助。

答案 3 :(得分:3)

这是我做类似事情的代码。这是我的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 };
        }
    }

基本查询是Select(f => f),这基本上意味着一切,Where子句可选地附加到它上面。最终的Select是可选的。我用来将数据库行对象转换为结果“Fruit”对象。

答案 4 :(得分:3)

我只是在我的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();
}

答案 5 :(得分:2)

根据某些条件添加where条件 ...

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="under-navigation">
  <div id="search" class="search">
    DIV 1
  </div>
  <div id="category-dropdown-1" class="category-dropdown-1">
    <div class="category-menu">
      DIV 2
    </div>
  </div>
</div>

答案 6 :(得分:0)

假设以下参数,

Int? Age = 18;

只需使用&&||条件运算符,我们就可以拥有另一个版本。

(from u in DataContext.Users
where u.Division == strUserDiv 
    && (Age == null || u.Age > Age)
    && (Param1 == null || u.param1 == Param1)
    && u.Height > strHeightinFeet
select new DTO_UserMaster
{
    Prop1 = u.Name,
}).ToList();

就像Param1一样,您可以添加任意数量的搜索条件参数。

答案 7 :(得分:0)

我只是偶然发现了这个东西,但以为我会使用lambda版本。

首先,我将创建一个类似这样的类以将参数传递到数据层:

   public class SearchParameters() {
       public int? Age {get; set;}
       public string Division {get;set;}
       etc
    }

然后,在我的数据层中,如下所示:

public IQueryable<User> SearchUsers(SearchParameters params) 
{
    var query = Context.Users;
    if (params.Age.HasValue)
    {
         query = query.Where(u => u.Age == params.Age.Value);
    }
    if (!string.IsNullOrEmpty(params.Division)
    {
        query = query.Where(u => u.Division == params.Division);
    }
    etc
    return query;
}

具体在哪里实现查询由您决定。应用程序和数据之间可能会有一层,可以将特定于数据库的表示形式转换为与数据库无关的(也许您查询多个数据源)。例如,该层可能会从这些来源获取多种类型的可查询对象,并将它们映射到公共POCO表示形式。

答案 8 :(得分:0)

只需添加到上面接受的答案here中, 如果要在联接上进行动态搜索,请考虑在初始linq查询中返回包含两个表(t1,t2)的新对象,以便您可以单独访问它们以进行条件搜索。

var query = from t1 in _context.Table1
            join t2 in _context.Table2 on t1.Table1Id equals t2.Table1IdId
            select new { t1, t2 };

        if (!string.IsNullOrEmpty(searchProperty1))
        {
            query = query.Where(collection => collection.t1.TableColumn == searchProperty1);
        }
        if (!string.IsNullOrEmpty(searchProperty2))
        {
            query = query.Where(collection => collection.t2.TableColumn == searchProperty2);
        }
        ....etc.

我得到了我在寻找here方面的答案,涉及到联接两个表并查询其中两个表中的特定列