0

假设纯多对多,其中主键是两个外键的组合。例如,Northwind 中的“Employee Privileges”具有 EmployeeID 和 PrivilegeID。这个 m2m 显然将Employees 表与Privilege 表相关联。

我需要使用 EF 编写一个查询,该查询返回与指定 PrivilegeID 无关的所有员工,无论它是否与其他 PrivilegeID 相关。

我有一个适用于 Sql Server 的 EF 查询,Except()但它不适用于 Oracle。

如果我在 t-sql 中编写查询,我会编写一个查询来过滤具有所需特权的员工特权“请参阅下面的 EmpPrivQuery”。然后,我会将 EmpPrivQuery 加入到 Employee 中,如EmployeesMissingPrivileges 中所见,以完成过滤器。

我们目前有具有关系属性的 Employee 和 Privilege 模型来创建多对多表。该项目首先使用 EF 代码来创建架构。

这可以用 EF 连接语法来完成吗?可以在不为 EmployeePrivilege 表创建实体模型的情况下完成吗?

EmpPrivQuery:
SELECT [Employee Privileges].[Employee ID], [Employee Privileges].[Privilege ID] 
FROM [Privileges] INNER JOIN [Employee Privileges] ON Privileges.[Privilege ID] = [Employee Privileges].[Privilege ID]
WHERE (((Privileges.[Privilege Name])="P3"));


EmployeesMissingPrivileges:
SELECT EmpPrivQuery.[Employee ID], Employees.*
FROM Employees LEFT JOIN EmpPrivQuery ON Employees.ID = EmpPrivQuery.[Employee ID]
WHERE (((EmpPrivQuery.[Employee ID]) Is Null));

该块位于原始帖子中,但使问题变得模糊。保留评论上下文。 我使用 Devart dotConnect 作为 Oracle 数据提供者。Oracle 抛出的错误是ORA-00904: "Extent1"."EmployeeID": invalid identifier. 在调整为 sql server 编写的代码库以针对 oracle 工作时,这是我需要解决的常见错误。在大多数情况下,我已经能够通过重写查询来解决它,以便使用 SelectMany() 将与其他表的关系从 WHERE 谓词(它很容易成为动态)移到查询的主体中。这往往会使发送到数据库服务器的查询变平,而 Oracle 似乎需要这样做。

4

1 回答 1

1

您可以使用 EF 创建与问题中发布的基本相同的查询。我首先创建了一个具有以下属性的 poco 模型 EmployeePrivilege:int PrivilegeID 和 int EmployeeID。我没有将此添加到 DbContext。

var EmpPrivQuery = ctx.Privileges
                       .Where(p => p.PrivilegeName == "P3")
                       .SelectMany(p => p.Employees, (p, e) => new EmployeePrivilege{EmployeeID = e.EmployeeID, PrivilegeID = p.PrivilegeID}
                       .Distinct();

var employeesMissingPrivilege = from e in Employees
                                join epq in EmpPrivQuery
                                on e.EmployeeID equals epq.EmployeeID
                                into jointable
                                where jointable.Count()==0
                                select e;

我刚刚意识到您也可以在不创建 poco EmployeePrivilege 的情况下获得相同的结果,如下所示:

var EmpPrivQuery = ctx.Privileges
                        .Where(p => p.PrivilegeName == "P3")
                        .SelectMany(p => p.Employees.Select(e => e.EmployeeID)
                        .Distinct();

var employeesMissingPrivilege = from e in Employees
                                join epq in EmpPrivQuery
                                on e.EmployeeID equals epq
                                into jointable
                                where jointable.Count()==0
                                select e;

这两个 EF 查询都返回员工缺少针对 Sql Server 和 Oracle 的指定权限(使用 Devart 的 dotConnect for Oracle)。

我读过的许多帖子都提到了使用DefaultIfEmpty()左外连接来实现。上面的查询有效,但是,如果有更好的方法使用DefaultIfEmpty().

于 2012-12-27T20:07:22.127 回答