C# LINQ:仅当值不为null时添加where子句
我知道一个典型的方式是这样的:C# LINQ:仅当值不为null时添加where子句,c#,asp.net,linq,performance,sql-server-2008,C#,Asp.net,Linq,Performance,Sql Server 2008,我知道一个典型的方式是这样的: IQueryable query = from staff in dataContext.Staffs; if(name1 != null) { query = from staff in query where (staff.name == name1); } IQueryable query = from staff in dataContext.Staffs; query = from staff in query where (name1 ==
IQueryable query = from staff in dataContext.Staffs;
if(name1 != null)
{
query = from staff in query where (staff.name == name1);
}
IQueryable query = from staff in dataContext.Staffs;
query = from staff in query where (name1 == null || staff.name == name1);
IQueryable<Staffs> query = dataContext.Staffs.AsQueryable().WhereIf(name1 != null, x => x.Name == name1);
IQueryable<Partners> recs = contextApi.Partners;
if (status != -1)
{
recs = recs.Where(i => i.Status == status);
}
recs = recs.OrderBy(i => i.Status).ThenBy(i => i.CompanyName);
foreach (var rec in recs)
{
}
然而,从我们从其他开发人员手中接手的一个程序中,我们看到了如下代码:
IQueryable query = from staff in dataContext.Staffs;
if(name1 != null)
{
query = from staff in query where (staff.name == name1);
}
IQueryable query = from staff in dataContext.Staffs;
query = from staff in query where (name1 == null || staff.name == name1);
IQueryable<Staffs> query = dataContext.Staffs.AsQueryable().WhereIf(name1 != null, x => x.Name == name1);
IQueryable<Partners> recs = contextApi.Partners;
if (status != -1)
{
recs = recs.Where(i => i.Status == status);
}
recs = recs.OrderBy(i => i.Status).ThenBy(i => i.CompanyName);
foreach (var rec in recs)
{
}
如果这是一个普通的SQL语句,我肯定会说第二个是一个糟糕的做法。因为当name1为null时,它会在查询中添加一个无意义的where子句
但我对LINQ是新手,所以我不确定LINQ是否与众不同 通常,使用流畅的语法(而不是查询语法)编写此类内容会让人感觉更流畅 e、 g 因此,如果
name1
为空,则不执行任何Where()
调用。如果您有多个不同的过滤器,所有这些过滤器可能都是必需的,也可能不是必需的,还有各种不同的排序顺序,我发现这将变得更易于管理
为alex编辑:好的,我刚才回答了一个问题,即仅当值不为null时才添加where子句。在回答问题的另一部分时,我使用EntityFramework4进行了尝试,以查看LINQ生成了什么样的SQL。您可以通过将query
强制转换为ObjectQuery
并调用.ToTraceString()
来完成此操作。结果是,WHERE
子句出现如下:
WHERE @p__linq__0 IS NULL OR [Extent1].[name] = @p__linq__1
因此,是的,这是典型的坏SQL,如果在name
列上有索引,不要期望使用它
编辑#2:再次尝试使用LINQ to SQL而不是实体框架,结果截然不同。这一次,尝试使用
name1
为null的查询将导致根本没有WHERE
子句,正如您所希望的那样;用name1
作为“a”进行尝试,结果得到了一个简单的,其中[t0].[name]=@p0
和@p0
作为“a”发送。实体框架并没有这样优化。这有点令人担忧。LINQ在其他一些原因上有所不同(不是在这个原因上),
LINQ是一种以“更快的方式”获取数据的方法,它具有少量代码和尽可能清晰的cod,LINQ有许多好处:
public static class LinqExtensions
{
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> whereClause)
{
if (condition)
{
return query.Where(whereClause);
}
return query;
}
}
IQueryable<Staffs> query = dataContext.Staffs.AsQueryable().WhereIf(name1 != null, x => x.Name == name1);
Expression<Func<SomeEfPoco, bool>> columnBeingFilteredPredicate = x => true; // Default expression to just say yes
if (!string.IsNullOrWhiteSpace(someColumnBeingFilteredValue))
{
columnBeingFilteredPredicate = x => x.someColumnBeingFiltered == someColumnBeingFilteredValue;
}
_context.SomeEfPocos.Where(x => ..... &&
..... &&
..... &&)
.Where(columnBeingFilteredPredicate);
IQueryable<Partners> recs = contextApi.Partners;
if (status != -1)
{
recs = recs.Where(i => i.Status == status);
}
recs = recs.OrderBy(i => i.Status).ThenBy(i => i.CompanyName);
foreach (var rec in recs)
{
}
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> whereClause)
=> condition ? query.Where(whereClause) : query;