2010-06-23 71 views
1

如果我有一组类似的员工数据:分级分层Linq中

var users = new[] 
{ 
    new {SupervisorId = "CEO", UserId = "CEO", UserName = "Joe"}, 
    new {SupervisorId = "CEO", UserId = "CIO", UserName = "Mary"}, 
    new {SupervisorId = "CIO", UserId = "XDIR", UserName = "Ed"}, 
    new {SupervisorId = "CIO", UserId = "YDIR", UserName = "Lisa"}, 
    new {SupervisorId = "XDIR", UserId = "AMNGR", UserName = "Steve"}, 
    new {SupervisorId = "AMNGR", UserId = "ASUP", UserName = "Lesley"} 
}; 

是否可以使用Linq添加分级层,在这个意义上说:

  • CEO = 1(顶部)
  • CIO = 2(第二级)
  • XDIR和YDIR = 3(第三级)
  • AMNGR = 4(等)
  • ASUP = 5(等)

我已经能集团员工根据SupervisorId,但不知道如何使“水平”发生。

var userGroups = from user in users 
    group user by user.SupervisorId into userGroup 
    select new 
    { 
    SupervisorId = userGroup.Key, 
    Level = ?????? 
    Users = userGroup.ToList() 
    }; 

    foreach (var group in userGroups) 
    { 
    Console.WriteLine("{0} - {1} - {2}", group.SupervisorId, group.Level, group.Users.Count); 
    } 

非常感谢。

+0

您是否希望级别适用于组中的所有成员。如果你看看集团首席执行官,那么有2个级别。 – 2010-06-23 12:50:01

+0

@Leom,CEO supervisorid是多余的,首席执行官监督=首席执行官。所以这个想法是,在SupervisorId = UserId的情况下,你是首席执行官 - 树从那里开始。 – dizzyguy 2010-06-23 16:23:52

回答

0

我想补充的排名到您的LINQ“用户对象”

public class User{ 

    public string SupervisorId {get;set;} 
    public string UserId {get;set;} 
    public string UserName {get;set;} 
    public int Level {get { return GetRank(SupervisorId ) ; } } 

    private int GetRank(string userId){ 
    if(string.IsNullOrEmpty(userId)){ 
     //Bad case, probably want to use a very large number 
     return -1; 
    } 
    int level = 0; 
    switch(userId){ 
     case "CEO": 
      level = 0; 
      break; 

     //insert others here 

    } 

    } 
} 

那么你的Linq您将添加一个连接。

 var userGroups = from user in users 
        join super in users on user.SupervisorId equals super.UserId 
        group user by user.SupervisorId into userGroup 
        select new 
    { 
     SupervisorId = userGroup.Key, 
     Level = super.Level, 
     Users = userGroup.ToList() 
    }; 
0

更新

继承人之一,创建一个查找表为每个级别的方式。它相当,我不知道它会如何扩大。显然,您需要调整它以从数据库中提取行。

定义一个类来保存我们的查找表

public class user{ 
    public string SupervisorId; 
    public string UserId; 
    public int Level; 
} 

然后我们得到用户名/ SupervisorId组合和循环的唯一列表通过列表计算每个组合的水平通过“走”了树。

var uniqueusers = (new user[] 
     { 
      new user {SupervisorId = "CEO", UserId = "CEO"}, 
      new user {SupervisorId = "CEO", UserId = "CIO"}, 
      new user {SupervisorId = "CIO", UserId = "XDIR"}, 
      new user {SupervisorId = "CIO", UserId = "YDIR"}, 
      new user {SupervisorId = "XDIR", UserId = "AMNGR"}, 
      new user {SupervisorId = "AMNGR", UserId = "ASUP"} 
     }).Distinct(); 


     foreach (var item in uniqueusers) 
     {   
      int level = 0; 
      user CurrentUser = item; 
      while (CurrentUser.UserId != CurrentUser.SupervisorId){ 
       CurrentUser = uniqueusers.Where(c => c.UserId == CurrentUser.SupervisorId).FirstOrDefault(); 
       level++; 
      } 
      item.Level = level;    
     } 

现在,您可以使用uniqueusers作为查找表来确定查询的级别。例如:

private int GetLevel(string userId){   
    return uniqueusers.Where(c => c.UserId == userId).FirstOrDefault().Level;  
    } 

你甚至可以用一点努力将它结合成一个单一的步骤。

+0

与上述相同的问题...结果实际上来自数据库,我无法对任何类型的分层进行硬编码。该代码需要能够基于以下想法来推断该级别: 1)CEO是顶级节点,其中supervisorID - userID和 2)下面的每个图层都由supervisorID定义,例如,如果您的主管是首席执行官,那么你是第2级,等等...... – dizzyguy 2010-06-23 16:30:39

+0

如果你的主管是首席执行官,你的用户是首席执行官,那么你是首席执行官,让我纠正第二条陈述。但如上所述,它适用于下面的每个级别。 – dizzyguy 2010-06-23 16:31:46

+0

这看起来非常有前途!我今天会试一试。谢谢! – dizzyguy 2010-06-25 13:29:14

0
ILookup<string, User> subordLookup = users 
    .ToLookup(u => u.SupervisorId); 

foreach(User user in users) 
{ 
    user.Subordinates = subordLookup[user.UserId].ToList(); 
} 

User userHierarchy = user.Single(u => u.UserId == "CEO"); 

免责声明:

  • 不处理多个老总。
  • 保留循环关系。
  • 遗落的孤儿。
+0

我目前没有定义用户类型。你可以解释一下我将如何去实现它? – dizzyguy 2010-06-23 16:27:04

+0

我将尝试将User作为一个具有上面定义的特性的新类来实现,看看它是否有效。 – dizzyguy 2010-06-23 16:34:00

0

这是你在找什么?

  var levels = new[] 
     { 
      new { Level = 1, LevelName = "CEO" }, 
      new { Level = 2, LevelName = "CIO" }, 
      new { Level = 3, LevelName = "XDIR" }, 
      new { Level = 3, LevelName = "YDIR" }, 
      new { Level = 4, LevelName = "AMNGR" }, 
      new { Level = 5, LevelName = "ASUP" } 
     };       

     var userGroups = from user in users 
         join level in levels on 
         user.UserId equals level.LevelName        
         group new{ User = user, Level = level.Level } by new { SuperId = user.SupervisorId, Level = level.Level } into userGroup 
         select new 
          { 
           SupervisorId = userGroup.Key.SuperId, 
           Level = userGroup.Key.Level, 
           Users = userGroup.ToList() 
          }; 
+0

问题是我正在从数据库中检索这个值。对象用户的代码只是一个例子。我的数据库只包含用户标识和管理员标识,我需要能够根据这个标准来更新层次结构 - 以CEO为根。 – dizzyguy 2010-06-23 16:28:25