代码之家  ›  专栏  ›  技术社区  ›  crichavin

实体框架linq到sql转换问题

  •  1
  • crichavin  · 技术社区  · 7 年前

    使用EF6/linqtosql来获得期望的结果。我宁愿不必在数据库中创建视图。

    我的linq谓词:

    .Where(x => 
       (x.AccountId == viewModel.AccountId || x.AccountId == null)
       && (x.CompanyId == viewModel.CompanyId || x.Company == null)
       && (x.FacilityId == viewModel.FacilityId || x.FacilityId == null)
    )
    

    生成的SQL:

    WHERE 
       (([Extent1].[AccountId] = 1) 
        OR (([Extent1].[AccountId] IS NULL) AND (1 IS NULL)) 
        OR ([Extent1].[AccountId] IS NULL)
       ) 
       AND 
       (
        ([Extent1].[CompanyId] = 11) 
        OR (([Extent1].[CompanyId] IS NULL) AND (11 IS NULL)) 
        OR ([Extent2].[Id] IS NULL)
       ) 
       AND 
       (
        ([Extent1].[FacilityId] = 1) 
        OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL)) 
        OR ([Extent1].[FacilityId] IS NULL)
       )  
       AND 
       (
        ([Extent1].[FacilityId] = 1) 
        OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL))
       )
    

    WHERE 
    (
        ([Extent1].[AccountId] = 1) 
        OR ([Extent1].[AccountId] IS NULL)
    ) 
    AND 
    (
        ([Extent1].[CompanyId] = 11) 
        OR ([Extent2].[Id] IS NULL)
    ) 
    AND 
    (
        ([Extent1].[FacilityId] = 1) 
        OR ([Extent1].[FacilityId] IS NULL)
    ) 
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   yv989c    7 年前

    请尝试:

    .Where(x => 
       (x.AccountId == (int)viewModel.AccountId || x.AccountId == null)
       && (x.CompanyId == (int)viewModel.CompanyId || x.Company == null)
       && (x.FacilityId == (int)viewModel.FacilityId || x.FacilityId == null)
    )
    

    var accountId = viewModel.AccountId.GetValueOrDefault();
    var companyId = viewModel.CompanyId.GetValueOrDefault();
    var facilityId = viewModel.FacilityId.GetValueOrDefault();
    ...
    ...
    .Where(x => 
       (x.AccountId == accountId || x.AccountId == null)
       && (x.CompanyId == companyId || x.Company == null)
       && (x.FacilityId == facilityId || x.FacilityId == null)
    )
    

    您的原始查询引用可为null的类型作为参数,因此,EF需要生成一个谓词,当您的参数值为null时,该谓词能够以可预测的方式工作,这就是为什么您将看到额外的 ([Extent1].[AccountId] IS NULL) AND (@p__linq__0 IS NULL) System.Int32 ),EF将看不到这样做的必要性,因为它“认为”您的参数不能为null。

    所有这些都是必需的,因为默认情况下,SQL server连接将具有该选项 ANSI_NULLS 在上,这意味着任何与 NULL 将为false,这就是为什么EF需要生成这个额外的逻辑( IS NULL 运算符),以确保在参数值为null时可以获得可预测的结果。

    你可以试试这个,看看它的效果 在行动中:

    SET ANSI_NULLS ON;
    SELECT 1 WHERE NULL = NULL;
    
    SET ANSI_NULLS OFF;
    SELECT 1 WHERE NULL = NULL;