Linq to Entities 多对多加入

发布于 2024-12-20 03:43:43 字数 1695 浏览 2 评论 0原文

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

我有 4 个表:

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

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

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

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

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

我需要检索以下内容的组合:

  • 不存在的所有客户订单状态为“进行中”
  • 当前员工的状态为“进行中”的任何额外记录
  • 任何状态的额外记录> 的“进行中”,其中工作人员是以下组织的成员与客户订单相同的部门。

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

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,他们会看到客户订单 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 toEntity 的新手,我一直在使用 linq-to-sql。任何建议将不胜感激 - 我什至不确定如何正确描述我正在尝试执行的连接类型。

My first time using the Entity Framework so I'm not sure if I'm doing this right.

I have 4 tables:

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

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

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

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

A staff member can belong to multiple departments. The StaffDept table is just for storing this many-to-many relationship.

I need to retrieve a combination of:

  • all Customer Orders that don't have a Status of "In Progress"
  • any extra records for the current Staff member with a Status of "In Progress"
  • any extra records with a Status of "In Progress" where the Staff member is a member of the same department as the Customer Order.

for example if I have the following data:

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, ...

I would expect if the current user was #1 they would see customer orders 1,2,3. User #2 would see 2,3,4.

Here is the code I have so far:

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,
    ...
}

which works, but Resharper complains that the FirstOrDefault() part will throw a NULL exception at runtime. I've tested with a User of #3 (which doesn't exist) in Linqpad and it doesn't throw an error - it returns just record 2 which is what I would expect. Resharper wants me to pull the Staffs.Where(x => x.StaffID == 3).FirstOrDefault() out into a separate query run before the query above, but I'm thinking that will make it slower? I'm really not sure that any of this query is the fastest way to get the data as I'm new to linq to entities, I've been using linq-to-sql. Any advice would be greatly appreciated - I'm not even sure how to correctly describe the type of join I'm trying to do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

养猫人 2024-12-27 03:43:43

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

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)

Since you are simply retrieving a member of the Staff by its primary key, and you know there will be exactly one staff member by that ID, you should replace FirstOrDefault with Single.

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

Edit 1:

Perhaps you can fold your query a bit:

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

Edit 2:

Staff.Any(x => x.StaffID == @CurrentStaffID && x.Depts.Any(d => d.DeptID == co.DeptID)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文