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

我有个问题

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

123994 次浏览

一个选择。

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

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

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

下面是我做类似事情的代码。这是我的 WCF SOAPWeb 服务 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是可选的。我用来将数据库行对象转换为结果“水果”对象。

我通常使用方法链接,但也有同样的问题

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也是有帮助的。

很简单,我在 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();
}

根据一定条件添加 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();

假设参数如下,

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一样,您可以为搜索条件添加任意数量的参数。

我只是偶然发现了这个,想找点别的东西,但觉得应该加上 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 (可能查询多个数据源)。例如,该层可以从这些源获得多种类型的查询,并将它们映射到公共 POCO 表示。

仅仅为了补充上述已接受的答案 给你, 如果您正在对一个连接进行动态搜索,请考虑在初始的 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.

我得到了答案,我正在寻找 给你关于联接两个表和查询具体的列对任何一个表