具有嵌套多对多关系的 LINQ to Entity Framework 错误

Ell*_*ppe 2 c# linq oracle entity-framework

我有以下对象结构(简化了一点......),其中一个用户被赋予一个角色,该角色属于一个或多个组,每个组都有一组权限(带有名称)。由于一个权限可以属于多个组,一个组可以包含多个角色,所以结构如下:

用户 -> 角色 ->> RoleToGroup -> 组 - >> GroupToPrivilege -> 权限(->> = 列表):

我需要找出是否有任何用户拥有名称为“name”的权限。

我尝试使用以下 Linq 语句,我认为它会给我正确的答案:

DbContext.RootObject.Where (x => x.Role.RoleToGroup.Any(y => y.Group.GroupToPrivilege.Any(z=> z.Privilege.Name == "Name")))
Run Code Online (Sandbox Code Playgroud)

这给出了以下sql:

SELECT 
"Extent1"."ROLE_ID" AS "ROLE_ID", 
FROM "USER" "Extent1"
WHERE ( EXISTS (SELECT 
    1 AS "C1"
    FROM ( SELECT 
    "Extent2"."GROUPS_ID" AS "GROUPS_ID"
    FROM "ROLETOGROUP" "Extent2"
    WHERE ("Extent1"."ROLE_ID" = "Extent2"."ROLE_ID")
)  "Project1"
WHERE ( EXISTS (SELECT 
    1 AS "C1"
    FROM  "GROUPTOPRIVILEGE" "Extent3"
    INNER "PRIVILEGE" "Extent4" ON "Extent3"."PRIVILEGES_ID" = "Extent4"."ID"
    WHERE (("Project1"."GROUPS_ID" = "Extent3"."GROUP_ID") AND ('Name' = "Extent4"."NAME"))
    ))
))
Run Code Online (Sandbox Code Playgroud)

运行时,我收到以下错误:

ORA-00904: "Extent1"."ROLE_ID": 无效标识符

如果我删除查询的“Exten1”部分,它运行正常:

SELECT 
"Extent1"."ROLE_ID" AS "ROLE_ID", 
FROM "USER" "Extent1"
WHERE ( EXISTS (SELECT 
1 AS "C1"
FROM ( SELECT 
    "Extent2"."GROUPS_ID" AS "GROUPS_ID"
    FROM "ROLETOGROUP" "Extent2"
    WHERE ("ROLE_ID" = "Extent2"."ROLE_ID")
)  "Project1"
WHERE ( EXISTS (SELECT 
    1 AS "C1"
    FROM  "GROUPTOPRIVILEGE" "Extent3"
    INNER "PRIVILEGE" "Extent4" ON "Extent3"."PRIVILEGES_ID" = "Extent4"."ID"
    WHERE (("Project1"."GROUPS_ID" = "Extent3"."GROUP_ID") AND ('Name' = "Extent4"."NAME"))
    ))
))
Run Code Online (Sandbox Code Playgroud)

但是我怎样才能让 Entity Framework 用 Linq 做同样的事情呢?

Kas*_*ols 5

Oracle 不会关联嵌套超过一层的子查询。

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1853075500346799932

这意味着嵌套 2 层深的子查询不能引用顶级表。这是 Oracle 的限制。

删除"Exten1"查询的一部分会给你一种错觉,它的工作原理是"ROLE_ID"指同级子查询中的列(在这种情况下"Extent2"."ROLE_ID"),查询结果将是错误的。

直接影响生成的 SQL 是相当困难的。

最简单的解决方案是将现有查询拆分为多个查询。首先从获取权限开始,然后找到匹配的 GroupToPrivilege 条目,依此类推,直到找到用户。

另一种选择是创建存储过程或视图来检索必要的数据。