C # Linq или запрос IEnumerable - PullRequest
       18

C # Linq или запрос IEnumerable

0 голосов
/ 15 января 2019

У меня есть таблица Employee, в которой также есть информация о руководителе отдела. Мне нужно заполнить два раскрывающихся списка - один с сотрудниками, а другой с менеджерами. Вместо того, чтобы использовать два запроса для извлечения сотрудников и другой запрос для извлечения менеджеров, я запрашиваю таблицу один раз и сохраняю всю информацию в кеше в IEnumerable EmployeeList.

Мне нужен какой-то запрос, чтобы вытащить менеджеров из этого запроса - либо используя LINQ, либо цикл внутри кода C #. Я написал цикл, но он очень неэффективен.

Вот SQL-запрос для заполнения HCache:

    SELECT [Dept_Mgr_ID] As MgrId,
            EmployeeId,
        EmpLastName,
        EmpFirstName
        FROM Employee_tbl

Здесь я пытаюсь перебрать кеш и соединить EmployeeId и MgrId

            List<DTO.Employee> Mgrs = new List<DTO.Employee>(0);
            for (int i = 0; i < HCache.EmployeeList.Count(); i++)
            {
                foreach(var e in HCache.EmployeeList)
                {

                    if (HCache.EmployeeList.ElementAt(i).EmployeeId == e.MgrId)
                    {

                        Mgrs.Add(new DTO.Employee() { MgrID = e.MgrId,

                            ManagerLastName = e.EmpLastName,
                            ManagerFirstName = e.EmpFirstName
             });
                    }
                }
            }

Я не использую этот запрос, однако я могу получить результаты, используя второй запрос для получения менеджеров:

 WITH CTE_Manager_ID
        AS
        (
        SELECT DISTINCT [Dept_Mgr_ID]
        FROM Employee_tbl
        )
        SELECT EmployeeId,
            EmpLastName,
            EmpFirstName
        FROM Employee_tbl Emp
        INNER JOIN CTE_Manager_ID cteMgr 
            ON cteMgr.Dept_Mgr_ID = Emp.EmployeeId

1 Ответ

0 голосов
/ 15 января 2019

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

Проблемы:

  • Предполагая, что EmployeeList - это IEnumerable, EmployeeList.ElementAt(i) - это операция O (n), то есть медленная. За кулисами это вложенный цикл.
  • EmployeeList.Count() является операцией O (n), то есть медленной.
  • Получаемая сложность вашего кода равна O (n ^ 3), т. Е. Очень медленно.

Как улучшить:

  • Сделайте один проход, чтобы построить карту от EmployeeId до Employee (или что вы храните в HCache.EmployeeList). Это позволит вам быстро найти их по идентификатору (в O (1)).
  • Сделайте еще один проход через EmployeeList, чтобы собрать менеджеров.
  • Общая сложность O (n), то есть пропорциональна размеру EmployeeList коллекции.

Вот код, иллюстрирующий эту идею:

class Emp {
    public int EmployeeId {get;set;}
    public int MgrId {get;set;}
    public string EmpLastName {get;set;}
}
IEnumerable<Emp> EmployeeList = new List<Emp> {
    new Emp { EmployeeId = 1, MgrId = 0, EmpLastName = "boss" },
    new Emp { EmployeeId = 2, MgrId = 1, EmpLastName = "dude" } };
IDictionary<int, Emp> dict = EmployeeList.ToDictionary(e => e.EmployeeId);
var managers = EmployeeList
  .Select(e => dict.TryGetValue(e.MgrId, out Emp mgr) ? mgr : null)
  .OfType<Emp>()
  .ToList()
// List<Emp>(1) { Emp { EmpLastName="boss", EmployeeId=1, MgrId=0 } }

Обратите внимание, что этот код потенциально создает дубликаты в списке managers, которые могут быть, а могут и не совпадать с вашими, но ваш код ведет себя так, поэтому я сохранил поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...