3

我试图找出 linq to 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 to sql 查询找到具有 employeeId 5 和 6 的 supervisorId。该查询将仅返回 2。我可以使用 2 个 where 子句,但假设我想输入 3 个employeeId,我的查询必须修改。如果一个匹配的 SupervisorId 不存在传递的排列(例如:在这种情况下为 5,6,8),则结果将为 null 或空。

该函数如下所示:

int FindSuperVisorId(List<int> employeeIds);

对于这种情况,我真的不知道从哪里开始 linq to sql。

谢谢

4

3 回答 3

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

然后首先使用实体​​框架数据库(不幸的是不是 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 中所示。

尝试对 LINQ to SQL 执行相同操作失败,因为调用了 except 异常 “NotSupportedException:本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但包含运算符。”

于 2013-02-18T15:17:15.747 回答
1

所以我很确定这个查询应该被转换为 LINQ to SQL 的属性,但我不完全确定。

因此,首先我们按主管分组,以便我们为该主管提供员工序列。然后我们Except在两个方向上与您感兴趣的员工一起使用。如果这两个Except调用的计数为零,则集合完全相等。有更有效的方法可以确定两个集合在 linq-to-objects 中是否相等,但我怀疑它们是否会正确转换为 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();
于 2013-02-18T15:27:14.350 回答
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)));
}
于 2013-02-18T15:11:59.760 回答