获取父菜单的所有子级详细信息

时间:2018-12-23 11:49:42

标签: c# sql oracle oracle10g

我正在使用菜单访问权限系统,管理员可以在其中将用户分配给包含菜单访问权限的组。单独授予用户权限很简单。但是对于团体权限,我要匹配的条件很少。因此,这是表的结构和示例数据:

----USER DETAILS----
CREATE TABLE HRD.USER_DETAILS
(
  EMPNO VARCHAR2(20 BYTE),
  ENAME VARCHAR2(40 BYTE),
  ENTRY_DATE DATE,
  STATUS INT
);

EMP-0001    John    6/10/2018   1
EMP-0002    Jack    5/12/2018   1

----GROUP DETAILS----
CREATE TABLE HRD.GROUP_DETAILS
(
  GROUPNO VARCHAR2(20 BYTE),
  GROUPNAME VARCHAR2(40 BYTE),
  DETAILS VARCHAR2(100 BYTE),
  ENTRY_DATE DATE,
  STATUS INT
);

GROUP-0001  GROUP-1     1/1/2018    1
GROUP-0002  GROUP-2     1/1/2018    1

----MENU DETAILS----
CREATE TABLE HRD.MENU_DETAILS
(
  MENUNO VARCHAR2(20 BYTE),
  MENUNAME VARCHAR2(40 BYTE),
  DETAILS VARCHAR2(100 BYTE),
  PARENT VARCHAR2(10 BYTE),
  ENTRY_DATE DATE,
  STATUS INT
);

1001    User Details        0   1/1/2018    1
1002    Add User        1001    1/1/2018    1
1003    Department Details      0   1/1/2018    1
1004    Add Department      1003    1/1/2018    1

----ASSIGN MENU DETAILS----
CREATE TABLE HRD.ASSIGN_MENU_DETAILS
(
  GROUPNO VARCHAR2(20 BYTE),
  MENUNO VARCHAR2(20 BYTE),
  DETAILS VARCHAR2(100 BYTE),
  ENTRY_DATE DATE,
  STATUS INT
);

GROUP-0001  1001        1/1/2018    1
GROUP-0001  1004        1/1/2018    1

----USER GROUP DETAILS----
CREATE TABLE HRD.USER_GROUP_DETAILS
(
  EMPNO VARCHAR2(20 BYTE),
  GROUPNO VARCHAR2(20 BYTE),
  DETAILS VARCHAR2(100 BYTE),
  ENTRY_DATE DATE,
  STATUS INT
);

EMP-0001    GROUP-0001      1/1/2018    1
EMP-0001    GROUP-0002      1/1/2018    1

因此,使用以下查询,我得到以下信息:

SELECT M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME FROM USER_GROUP_DETAILS m INNER JOIN ASSIGN_MENU_DETAILS k ON K.GROUPNO = M.GROUPNO
LEFT JOIN (SELECT P.MENUNO, P.MENUNAME FROM MENU_DETAILS p WHERE P.PARENT = '0' OR P.PARENT <> '0') q ON Q.MENUNO = K.MENUNO 
GROUP BY M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME;

EMP-0001    GROUP-0001  1001    User Details
EMP-0001    GROUP-0001  1004    Add Department

由于用户没有 GROUP-0002 的菜单权限,因此查询中不应显示任何菜单。这是最重要的事情: GROUP-0001 具有两个菜单权限1)用户详细信息2)添加部门

“用户详细信息”菜单是部门详细信息菜单的父级,而添加部门是子菜单。因此,我期望的是,每当分配了子菜单时,父菜单在查询中也应该可见。现在,添加部门菜单具有父级部门详细信息,因此父级也必须得到反映。

我不确定是否要使用查询或C#来执行此操作,但是也尝试使用C#代码来执行此操作,但是似乎逻辑构建得并不完美。

C#

foreach (var parent in GetViewModel())
{
   foreach (var child in GetViewModel2(parent.Parent))
   {
       sampleDynamicNav = new List<NavBarItem> {
            new NavBarItem {
                D = 1, Text = parent.MenuName, Icon = new ItemIcon {Default =  HRMS_New_VS2.Properties.Resources.nav_new_home, Hover = HRMS_New_VS2.Properties.Resources.nav_new_home, Selected = HRMS_New_VS2.Properties.Resources.nav_new_home}, ToolTip = "tooltip Main Menu", Height = 40,

                Childs = new List<NavBarItem> {
                    new NavBarItem {ID = child.MenuNo, Text = child.MenuName, Height = 30 },
               }
           }
       };
   }
}

public IEnumerable<EmpViewModel> GetParent()
{
     List<EmpViewModel> lstEmp = new List<EmpViewModel>();

     string query = "SELECT M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME, Q.PARENT FROM USER_GROUP_DETAILS m INNER JOIN ASSIGN_MENU_DETAILS k ON K.GROUPNO = M.GROUPNO " +
                    "LEFT JOIN (SELECT P.MENUNO, P.MENUNAME, P.PARENT FROM MENU_DETAILS p) q ON Q.MENUNO = K.MENUNO WHERE M.EMPNO = 'EMP-0001' " +
                    "GROUP BY M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME, Q.PARENT";

      DataTable dt = SelectData(query);

      if (dt != null && dt.Rows.Count > 0)
      {
          foreach (DataRow dr in dt.Rows)
          {
              EmpViewModel bo = new EmpViewModel();
              bo.Parent = dr["PARENT"].ToString();
              bo.MenuName = dr["MENUNAME"].ToString();
              bo.MenuNo = Convert.ToInt32(dr["MENUNO"].ToString());

              lstEmp.Add(bo);
          }
       }

     return lstEmp;
}



public IEnumerable<EmpViewModel> GetChild(string menuNo)
{
    List<EmpViewModel> lstEmp = new List<EmpViewModel>();

    string query = "SELECT M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME, Q.PARENT FROM USER_GROUP_DETAILS m INNER JOIN ASSIGN_MENU_DETAILS k ON K.GROUPNO = M.GROUPNO " +
                   "LEFT JOIN (SELECT P.MENUNO, P.MENUNAME, P.PARENT FROM MENU_DETAILS p) q ON Q.MENUNO = K.MENUNO WHERE M.EMPNO = 'EMP-0001' AND Q.PARENT = '" + menuNo + "'" +
                   "GROUP BY M.EMPNO, M.GROUPNO, K.MENUNO, Q.MENUNAME, Q.PARENT";

     DataTable dt = SelectData(query);

     if (dt != null && dt.Rows.Count > 0)
     {
         foreach (DataRow dr in dt.Rows)
         {
            EmpViewModel bo = new EmpViewModel();
            bo.Parent = dr["PARENT"].ToString();
            bo.MenuName = dr["MENUNAME"].ToString();
            bo.MenuNo = Convert.ToInt32(dr["MENUNO"].ToString());

            lstEmp.Add(bo);
         }
     }
    return lstEmp;
}

预期输出-对于菜单权限:用户的 GROUP-0001

Menu - 01: User Details
Menu - 02: Department Details
           -> Add Department

N.B::可以将一个用户分配给多个组,并且该组可以重复两次菜单权限。在那种情况下,它应该反映不同的菜单,使父菜单和子菜单保持相邻。暂时将其放在一旁。

1 个答案:

答案 0 :(得分:2)

您可以使用递归CTE来获取所有父菜单。

WITH 
CTE (MENUNO,
     MENUNAME,
     PARENT) AS
(
SELECT M.MENUNO,
       M.MENUNAME,
       M.PARENT
       FROM USER_DETAILS U
            INNER JOIN USER_GROUP_DETAILS UG
                       ON UG.EMPNO = U.EMPNO
            INNER JOIN ASSIGN_MENU_DETAILS AM
                       ON AM.GROUPNO = UG.GROUPNO
            INNER JOIN MENU_DETAILS M
                       ON M.MENUNO = AM.MENUNO
       WHERE U.EMPNO = 'EMP-0001'
UNION ALL
SELECT M.MENUNO,
       M.MENUNAME,
       M.PARENT
       FROM MENU_DETAILS M
            INNER JOIN CTE C
                       ON C.PARENT = M.MENUNO
)
SELECT DISTINCT
       MENUNO,
       MENUNAME
       FROM CTE;

db<>fiddle