Linq to Entities多对多加入

时间:2011-12-08 02:10:39

标签: c# linq-to-entities many-to-many resharper linqpad

我第一次使用实体框架,所以我不确定我是否正确这样做。

我有4张桌子:

CustomerOrder
------------
ID, StaffID, DeptID, Status, other columns...

Staff
------------
StaffID, other columns...

StaffDept
------------
StaffID, DeptID - only 2 fields

Dept
------------
DeptID, other columns...

工作人员可以属于多个部门。 StaffDept表仅用于存储这种多对多关系。

我需要检索以下组合:

  • 的所有客户订单都有Status“正在进行中”
  • 当前工作人员的任何额外记录Status“正在进行中”
  • Status“正在进行中”的任何额外记录,其中工作人员是与客户订单相同部门的成员。

例如,如果我有以下数据:

Staff
-----
1, Mr X, ...
2, Mr Y, ...

Dept
-----
1, Sales, ...
2, Marketing, ...

StaffDept
-----
1, 1
1, 2
2, 2

CustomerOrder
-----
1, 1, 1, In Progress, ...
2, 1, 1, Completed, ...
3, 2, 2, In Progress, ...
4, 2, NULL, In Progress, ...

我希望如果当前用户排名第一,他们会看到客户订单1,2,3。用户#2会看到2,3,4。

这是我到目前为止的代码:

from co in CustomerOrders
where co.Status != "In Progress" 
  || co.StaffID == @CurrentStaffID
  || (co.StaffID != @CurrentStaffID 
      && co.DeptID!= null 
      && Staffs.Where(x => x.StaffID == @CurrentStaffID).FirstOrDefault().Depts.Any(x => x.DeptID== co.DeptID))
select new CustomerOrderObject
{
    Description = co.Description,
    Amount = co.Amount,
    ...
}

有效,但Resharper抱怨FirstOrDefault()部分会在运行时抛出NULL异常。我已经在Linqpad中测试了#3用户(它不存在)并且它没有抛出错误 - 它只返回记录2,这是我所期望的。 Resharper希望我在上面的查询之前将Staffs.Where(x => x.StaffID == 3).FirstOrDefault()拉出到单独的查询运行中,但我认为这会让它变慢?我真的不确定这个查询是否是获取数据的最快方式,因为我是linq to entity的新手,我一直在使用linq-to-sql。任何建议都会非常感激 - 我甚至不确定如何正确描述我正在尝试的联接类型。

1 个答案:

答案 0 :(得分:2)

由于您只是通过其主键检索Staff的成员,并且您知道该ID只有一名工作人员,因此您应将FirstOrDefault替换为Single

Staffs.Single(x => x.StaffID == @CurrentStaffID).Depts.Any(x => x.DeptID== co.DeptID))

编辑1:

也许你可以稍微折叠你的查询:

StaffDept.Any(sd => sd.StaffId == @CurrentStaffID && sd.DeptID== co.DeptID)

编辑2:

Staff.Any(x => x.StaffID == @CurrentStaffID && x.Depts.Any(d => d.DeptID == co.DeptID)