2014-04-14 3 views
0

Я использую oracleDB, и у меня есть вид, как показано ниже, в котором содержатся сотрудники и его менеджеры.Лучший способ написать lingq для запросов цикла

empNo 
FirstName 
LastName 
Manager 

Мне нужно выбрать человека и все его сотрудники. IE

Person1 is Manager 
-- Person1_1 
----Person1_1_1 
----Person1_1_2 
-- Person1_1 

Когда я войти в систему с пользователем Person1, мне нужно, чтобы все лица, выше.

Вот мой LINQ, но он слишком медленный. Каков эффективный способ получить данные?

List<decimal> OrgPerson2 = new List<decimal>(); 
public List<decimal> getOrgPerson(decimal empNo) 
{ 
    List<decimal> OrgPerson = new List<decimal>(); 
    OrgPerson.AddRange(db.CRM_PERSON_TITLE_V.Where(c => c.MANAGER == empNo).Select(c => (decimal)c.PERSONID).ToList()); 
    var subPerson = db.CRM_PERSON_TITLE_V.ToList(); 

    foreach (var item in OrgPerson) 
    { 
     OrgPerson2.Add(item); 
     var subPerson2 = subPerson.Where(c => c.MANAGER == item).Select(c => (decimal)c.PERSONID).ToList(); 
     if (subPerson2 != null) 
     { 
      if (subPerson2.Count > 0) 
      { 
       getOrgPerson(item); 
      } 
     } 
    } 
    return OrgPerson2.Distinct().ToList(); 
} 
+0

Избавьтесь от всех вызовов ToList(), которые вы можете, они обычно действительно замедляют работу. Call ToList после создания коллекции. –

ответ

0

Решил попробовать ваше решение, и, как я подозревал, он выбрал для меня исключение StackOverflowException. Рекурсивные методы довольно плохи, если вы не будете осторожны.

Вот мое решение со стеком. Код не требует пояснений.

List<decimal> GetOrgPerson(decimal id) 
    { 
     Stack<Person> iter = new Stack<Person>(); 
     List<decimal> result = new List<decimal>(); 

     iter.Push(db.People.FirstOrDefault(p => p.ID == id)); 

     while (iter.Count() > 0) 
     { 
      Person current = iter.Pop(); 

      var subordinates = db.People.Where(p => p.ManagerID == current.ID); 

      foreach (var s in subordinates) 
      { 
       if (result.Contains(s.ID)) 
        continue; 

       iter.Push(s); 
       result.Add(s.ID); 
      } 
     } 
     return result; 
    } 

В моем тестовом случае люди наследуют IEnumerable интерфейс.

0

Ваш запрос просто получить все сотрудники под менеджером рекурсивно, он может быть значительно упрощена:

public IEmunerable<decimal> getOrgPerson(decimal empNo) 
{ 
    foreach (var subEmpNo in db.CRM_PERSON_TITLE_V.Where(c => c.MANAGER == empNo).Select(c => (decimal)c.PERSONID)) 
    { 
     yield return subEmpNo; 
     foreach (var subSubEmpNo in getOrgPerson(subEmpNo)) 
      yield return subSubEmpNo; 
    } 
} 

Вы не должны Distinct(), поскольку каждый сотрудник имеет только один менеджер.

Кроме того, я предполагаю, что вам не нужен List<decimal>, который вы можете добавлять/удалять. В противном случае вам может понадобиться что-то вроде OrgPerson2 = getOrgPerson(empNo).ToList()

Смежные вопросы