119

我有这样的查询

(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 块都有一个附加条件。有一个更好的方法吗?

4

9 回答 9

217

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

这仍然只会导致对数据库的一次调用,这将与一次性编写查询一样有效。

于 2012-06-04T16:31:47.203 回答
28

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

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很有帮助。

于 2016-03-11T02:07:19.880 回答
22

一种选择。

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 子句。

于 2012-06-04T16:28:06.983 回答
7

只是我在 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();
}
于 2016-12-15T22:58:28.627 回答
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();
于 2017-10-10T14:52:08.990 回答
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是可选的。我用来将数据库行对象转换为结果“水果”对象。

于 2015-05-19T20:37:11.900 回答
1

只是为了在此处添加上述接受的答案,如果您正在对连接进行动态搜索,请考虑在初始 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.

我得到了我在这里寻找的关于加入两个表和查询其中一个表上的特定列的答案

于 2020-02-21T11:05:12.807 回答
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;
}

在哪里实现查询取决于您。可能在应用程序和数据之间有一个层,它将特定于 db 的表示转换为 db-agnostic(也许您查询多个数据源)。例如,该层可能会从这些源中获取多种类型的可查询,并将它们映射到一个通用的 POCO 表示。

于 2019-12-05T21:05:10.783 回答
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 一样,您可以为搜索条件添加任意数量的参数。

于 2019-08-12T12:15:04.787 回答