2017-03-17 59 views
2

我有一张需要管理员签名的表单列表,我试图做的是将表单列表过滤到他们可以签出的表单。C#Linq Nullable INT字段包含在列表内<int> SQL翻译

我得到他们经理的员工名单,然后将其列入员工ID列表。

var staffIds = manager.Staff.Select(x => x.Id).ToList(); 

然后我使用职员列表筛选表格列表。

我得到的所有形式,这里它的认证机构标识,然后删除已经被拒绝任何形式的再检查,看是否格式匹配下列之一匹配 -

的形式还没有被“先签字关闭“,并且提交表格的工作人员由经过认证的工作人员管理。

形式已经“先签字”,而不是“第二签了字”和认证人员管理的工作人员谁做的第一个迹象了。

var forms = (from item in DbContext.Forms 
      where item.OrganisationId == authenticatedOrganisationId 
        && item.RejectStaffId == null 
        && ((item.FirstSignOffStaffId == null && staffIds.Contains(item.StaffId)) 
        || (item.FirstSignOffStaffId != null 
         && item.SecondSignOffStaffId == null 
         && staffIds.Contains(item.FirstSignOffStaffId.Value))) 
          select item).ToList(); 

问题是正在运行的SQL不正确。我期望的SQL的样子 -

SELECT * 
FROM [Forms] 
WHERE [OrganisationId] = 1 
    AND [RejectStaffId] IS NULL 
    AND (([FirstSignOffStaffId] IS NULL 
     AND [StaffId] IN (1,2,3,4)) 
     OR ([FirstSignOffStaffId] IS NOT NULL 
     AND [SecondSignOffStaffId] IS NULL 
     AND [FirstSignOffStaffId] IN (1,2,3,4))) 

但是,相反它运行

SELECT * 
FROM [Forms] AS [item] 
WHERE ([item].[OrganisationId] = 1) 
    AND [item].[RejectStaffId] IS NULL 

所以后来没有休息的记忆中,这意味着所有的形式(其随着时间的推移会变得非常大数据集)被返回。

我所发现的是,它打破当我添加

staffIds.Contains(item.FirstSignOffStaffId.Value) 

字段“FirstSignOffStaffId”是一个可空INT这似乎打破了SQL发送作为与“STAFFID是”领域中的罚款,但该是一个INT字段。

有谁知道如何使它与一个可空的INT字段正确运行?

+0

ORM什么是您使用?通常如果一个方法不被支持,它会在运行时抛出一个错误,而不是截断查询(尤其是因为它不会在查询点截断它。出于好奇,如果将列表构造为'列表'而不是? – Rob

+0

EF核心1.1 - 我尝试使它成为一个列表,它做了同样的事情 –

+0

即使删除'.Value'? – Rob

回答

2

随着EF核心这似乎是Contains行为为List <int?>本地执行,请参阅本issueList <GUID?>

0

让staffIds nullables(以避免在查询表达式类型转换)的列表。就像这样:

var staffIds = manager.Staff.Select(x => (int?)x.Id).ToList(); 

这就是为什么IQueryable的是抽象的坏榜样:你还必须知道很多关于底层提供...