我试图找出linq中对sql的正确查询,但我只是想弄清楚如何这样做。可以说我有一张下面的表(这个表基本上是一对多的关系)
Id (PK) | SupervisorId | EmployeeId
1 1 5
2 1 6
3 1 7
4 2 5
5 2 6
6 3 7
7 4 7
8 4 8
我希望我的linq到sql查询找到对employeeId 5和6有的supervisorId。查询只返回2。我可以使用2 where子句,但是让我说我想输入3个employeeIds,我的查询将不得不修改。如果一个匹配的SupervisorId存在传递的排列(例如,在这种情况下为5,6,8),则结果将为null或为空。
该功能如下所示:
int FindSuperVisorId(List<int> employeeIds);
我真的不知道在这种情况下从linq到sql的起点。
由于
答案 0 :(得分:1)
我必须将您的表格建模为多个关系,如下所示:
CREATE TABLE [dbo].[Employee](
[Name] [nvarchar](50) NOT NULL,
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[SupervisorEmployees](
[SupervisorId] [int] NOT NULL,
[EmployeeId] [int] NOT NULL,
CONSTRAINT [PK_SupervisorEmployees] PRIMARY KEY CLUSTERED
(
[SupervisorId] ASC,
[EmployeeId] ASC
)
GO
ALTER TABLE [dbo].[SupervisorEmployees] WITH CHECK ADD CONSTRAINT [FK_SupervisorEmployees_Employee] FOREIGN KEY([SupervisorId])
REFERENCES [dbo].[Employee] ([Id])
GO
ALTER TABLE [dbo].[SupervisorEmployees] CHECK CONSTRAINT [FK_SupervisorEmployees_Employee]
GO
ALTER TABLE [dbo].[SupervisorEmployees] WITH CHECK ADD CONSTRAINT [FK_SupervisorEmployees_Employee1] FOREIGN KEY([EmployeeId])
REFERENCES [dbo].[Employee] ([Id])
GO
ALTER TABLE [dbo].[SupervisorEmployees] CHECK CONSTRAINT [FK_SupervisorEmployees_Employee1]
GO
然后首先使用Entity Framework数据库(不幸的是Linq to SQL),以下LINQPad代码工作正常:
void Main()
{
FindSupervisorIds( new List<int>{5,6} ).Dump();
}
IEnumerable<int> FindSupervisorIds(List<int> employeeIds)
{
// two Excepts to do 'sequence equals'
var supervisors = Employees.Where (e =>
!e.Employees.Select (em => em.Id).Except(employeeIds).Any()
&& !employeeIds.Except(e.Employees.Select (em => em.Id)).Any()
);
return supervisors.Select (s => s.Id).Distinct();
}
int? FindSupervisorId(List<int> employeeIds)
{
var supervisors = FindSupervisorIds(employeeIds).ToList();
if(supervisors.Count == 1)
{
return supervisors.First ();
}
return null;
}
FindSupervisorIds生成单个SQL查询。如果您需要检查只有一个匹配的主管,最好在返回的主管列表上调用ToList(),如FindSupervisorId。
由于调用Except异常,尝试使用LINQ to SQL执行相同的操作失败 'NotSupportedException:除了Contains运算符之外,本地序列不能用于查询运算符的LINQ to SQL实现。'
答案 1 :(得分:1)
所以我很确定这个查询应该转换为LINQ to SQL的属性,但我不完全确定。
首先,我们由主管分组,以便我们为该主管提供一系列员工。然后,我们将Except
与您感兴趣的员工一起用于两个方向。如果这两个Except
调用的计数为零,则这些集合完全相等。有更有效的方法可以确定两个集合在linq到对象中是否相等,但我怀疑它们是否会正确转换为SQL代码。
var supervisorId = table.GroupBy(item => item.SupervisorId)
.Select(group => new
{
additionalItems = group.Select(item => item.EmployeeId).Except(employees),
missingItems = employees.Except(group.Select(item => item.EmployeeId)),
group = group
})
.Where(queries => queries.additionalItems.Count() == 0
&& queries.missingItems.Count() == 0)
.Select(queries => queries.group.Key)//gets the supervisorID
.FirstOrDefault();
答案 2 :(得分:0)
一种可能性:
public int FindSuperVisorId(IEnumerable<Employee> employes)
{
var distinctSupervisors = employes.Select(e => e.SuperVisor).Distinct();
var superVisor = distinctSupervisors.Where(supervisor => employes.All(employee => employee.SuperVisor.Equals(supervisor))).FirstOrDefault();
return superVisor;
}
如果你想要同一个主管的所有比赛:
public IEnumerable<int> FindSuperVisorId(IEnumerable<Employee> employes)
{
var distinctSupervisors = employes.Select(e => e.SuperVisor).Distinct();
var equalSupervisors = distinctSupervisors .Where(supervisor => employes.All(employee => employee.SuperVisor.Equals(supervisor)));
return equalSupervisors;
}
或直接:
public IEnumerable<int> FindSuperVisorId(IEnumerable<Employee> employes)
{
return employes.Select(e => e.SuperVisor).Distinct()
.Where(supervisor => employes.All(employee => employee.SuperVisor.Equals(supervisor)));
}