EF4 将 is null 子句添加到 where 子句

Posted

技术标签:

【中文标题】EF4 将 is null 子句添加到 where 子句【英文标题】:EF4 adding is null clause onto where clause 【发布时间】:2016-10-07 04:27:10 【问题描述】:

我有以下 linq 查询:

var fileDocuments = (
    from doc in fileUploads
    from invoice in
        (
            from inv in _dbContext.SupplierInvoiceHeaders
            where inv.InvoiceDocumentId == doc.ID || inv.JobSheetInvoiceId == doc.ID
            select inv
            ).DefaultIfEmpty()
    join pos in _dbContext.PurchaseOrders on invoice.PurchaseOrder.PurchaseOrderId equals pos.PurchaseOrderId into poss
    from po in poss.DefaultIfEmpty()
    join hdf in _dbContext.HelpDeskFaults on po.HelpdeskFaultId equals hdf.ID into hdfpo
    from hs in hdfpo.DefaultIfEmpty()
    join store1 in _dbContext.Stores on hs.StoreID equals store1.ID into hsf
    from hdfStore in hsf.DefaultIfEmpty()
    join js in _dbContext.JobSheets on invoice.SupplierInvoiceHeaderId equals js.SupplierInvoiceHeaderID into jss
    from jobSheets in jss.DefaultIfEmpty()
    join ch in _dbContext.ChildProjects on po.ChildProjectId equals ch.ID into chs
    from childProjects in chs.DefaultIfEmpty()
    join ph in _dbContext.ProjectHeaders on childProjects.ProjectHeaderID equals ph.ID into phs
    from projectHeaders in phs.DefaultIfEmpty()
    join ppmsl in _dbContext.PpmScheduleLines on projectHeaders.PPMScheduleRef equals ppmsl.ID into ppsmsls
    from ppmScheduleLines in ppsmsls.DefaultIfEmpty()
    join ss2 in _dbContext.Stores on ppmScheduleLines.StoreID equals ss2.ID into ssts
    from store2 in ssts.DefaultIfEmpty()
    select new
    
        doc.ID,
        JobSheetId = jobSheets.DocumentID,
        doc.Name,
        doc.DateCreated,
        doc.StoreID,
        StoreName = doc.Store.Name,
        DocumentType = doc.DocumentType.Name,
        doc.DocumentTypeID,
        HelpDeskFaultStoreName = hs.Store.Name,
        DocStoreName = doc.Store.Name,
        PPMScheduleLinesStoreName = ppmScheduleLines.Store.Name,
        PIR = invoice.PurchaseInvoiceReference
    );


    fileDocuments = fileDocuments.Where(x => x.PIR == jobSearchParams.PIR);

生成的 where 子句如下所示:

WHERE ([Extent2].[fld_str_PIR] = @p__linq__0) OR (([Extent2].[fld_str_PIR] IS NULL) AND (@p__linq__0 IS NULL))

我不明白为什么要添加 IS NULL 子句。

【问题讨论】:

【参考方案1】:

它会添加它们,因为您的 jobSearchParams.PIR 可能为空。如果它为空,EF 将假定您要返回 fld_str_PIR 为空的行。但是在 sql 中,您不能使用“=”运算符与 null 进行比较:

WHERE ([Extent2].[fld_str_PIR] = @p__linq__0) -- doesn't work if @p__linq__0 is null

这就是为什么它会为您处理这种情况并为这两种情况生成正确的查询 - 无论jobSearchParams.PIR 是否为空。

【讨论】:

有没有我可以在没有不需要的 IS NULL 子句的情况下生成一个相等检查? 如果它是可为空的类型(例如字符串、整数?等)——我对此表示怀疑。 可能知道它永远不能为空,但 EF 无法知道这一点,我不确定是否有办法告诉它它不能为空。如果它是可空值类型(int?) - 您可以首先将其值分配给相同类型(int)的不可空局部变量。但是,您对此有什么问题? 我不明白我想做的只是生成一个 where 子句,例如:WHERE ([Extent2].[fld_str_PIR] = @p__linq__0)) jobSearchParams.PIR 永远不会为空。 jobSearchParams.PIR 的类型是什么? @dagda1 其他地方有什么问题?我也有同样的问题。【参考方案2】:

经过大量搜索,我找到了另一篇突出显示 UseDatabaseNullSemantics 设置的帖子:

context.Configuration.UseDatabaseNullSemantics = true;

启用此设置后,我的查询将在 900 毫秒内运行,而不是超时。

【讨论】:

以上是关于EF4 将 is null 子句添加到 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:查询应用在 where 子句中,包含 Json 对象的列上的 IS NOT Null 需要更多时间

如何使用 AREL 执行条件 where 子句

Laravel 4:将 where 子句添加到连接条件

SQL Server If 条件在 where 子句?

SQL EXISTS vs. Aggregate IS NOT NULL

选择带有“is null”子句的查询和子选择/左连接不返回结果