【问题标题】:Linq remove where if the value is null如果值为 null,则 Linq 删除 where
【发布时间】:2016-02-04 07:42:54
【问题描述】:

我的 Linq 查询

var result = db.APPLICATIONS
.Where(a => Statuses.Contains(a.STATUS_ID))
.Where(a => a.TrackingNo == TrackingNo)

Statuses 是一个 int 列表,TrackingNo 是一个可为空的 int (int?)。

问题: 如果TrackingNo 为空,那么我不想运行这个子句或者只是跳过这个条件。

【问题讨论】:

  • var result = db.APPLICATIONS.Where(a => a.Statuses.Contains(a.STATUS_ID) && (a.TrackingNo != null && TrackingNo == TrackingNo))?
  • @Tim 我试过了。那不工作!实体未对条件进行分组

标签: c# entity-framework linq


【解决方案1】:

LINQ 查询可以通过多个步骤构建:

var result = db.APPLICATIONS
    .Where(a => Statuses.Contains(a.STATUS_ID));

if (TrackingNo != null)
{
    result = result.Where(a => a.TrackingNo == TrackingNo);
}

请注意,如果您有Select(投影),您可能必须在多个变量中的多个步骤中构建查询:

var result2 = result.Select(a => new { a.STATUS_ID });

result2if 之后“构建”。

【讨论】:

  • 这将被“构建”或者这将获取所有“包含 status_id 的应用程序”,然后在 trackingno 不为空时过滤它们?这对于大型查询来说会是一个问题吗?
  • @LeandroBardelli 这取决于null 的位置。如果Statusesnull,你会得到NullReferenceException。如果a.STATUS_IDnull 就不会出错。
  • 感谢您的回复。我的意思是(对不起我的英语)就是这个。假设对于第一个查询,您获得 1M 条记录,而对于第二个查询只有 3 条记录。内存中会有 1M 条记录还是只有 3 条?我认为它将执行到数据库,然后获取 1M 记录,然后将 1M 过滤为 3。执行是否有可能完成你有 linq?像“准备”一样?
  • @LeandroBardelli 当存在 First、FirstOrDefault、Single、SingleOrDefault、Count、Any、ToArray、ToList 或对查询结果执行 foreach 时,将执行查询。 LINQ 基于“延迟执行”。只有我命名的方法(和其他一些方法)会导致查询的执行
【解决方案2】:

您可以使用“HasValue”属性检查可为空的 int。

var result = db.APPLICATIONS
    .Where(a => Statuses.Contains(a.STATUS_ID))
    .Where(a => a.HasValue && (a.TrackingNo == TrackingNo))

这将导致它在检查值本身之前评估“HasValue”。如果 HasValue 返回 false,那么它将永远不会计算表达式的其余部分(因此不会导致 NullReferenceException)。 如果它是“int?”类型,那么这将起作用。

【讨论】:

    【解决方案3】:

    只需添加&& 条件并检查null。你可以在这里使用 1 where condiiton 为什么第二个 where. 请试试这个:

        var result = db.APPLICATIONS
                     .Where(a => Statuses.Contains(a.STATUS_ID) 
                     && a.TrackingNo!=null 
                     && a.TrackingNo == TrackingNo)
    

    【讨论】:

    • 这是大错特错
    【解决方案4】:

    在尝试向 store 表达式添加更多内容之前,您应该首先检查过滤参数的值。如果可为空的 TrackingNo 有值,这只会应用 Statuses 和 TrackingNo 过滤。否则,它会将所有 APPLICATIONS 作为 IQueryable 返回。

    var result = db.APPLICATIONS.AsQueryable();
    
    if (TrackingNo.HasValue)
    {
        result = result.Where(a => Statuses.Contains(a.STATUS_ID) && a.TrackingNo == TrackingNo);
    }
    
    return result;
    

    或者,这将检查您是否有任何要应用的状态和单独的跟踪。

    var result = db.APPLICATIONS.AsQueryable();
    
    if (Statuses != null && Statuses.Count() > 0)
    {
        result = result.Where(a => Statuses.Contains(a.STATUS_ID)); 
    }
    
    if (TrackingNo.HasValue)
    {
        result = result.Where(a => a.TrackingNo == TrackingNo);
    }
    
    return result;
    

    或者第三个选项,因为不清楚你真正想要什么。这将始终应用状态过滤并仅在可用时进行跟踪

    var result = db.APPLICATIONS.Where(a => Statuses.Contains(a.STATUS_ID));    
    
    if (TrackingNo.HasValue)
    {
        result = result.Where(a => a.TrackingNo == TrackingNo);
    }
    
    return result;
    

    【讨论】:

    • 感谢您的信息。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多