简体   繁体   中英

C# Linq or querying IEnumerable

I have an Employee table which also has Department Manager information. I need to populate two dropdowns - one with Employees and other with Managers. Instead of using two queries to pull employees and another query to pull managers, I am querying table once and storing all info in cache in an IEnumerable EmployeeList.

I need some query to pull managers from that query - either using LINQ or loop within C# code. I have written loop but it is very inefficient.

Here is the SQL query to populate HCache:

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

Here I am trying to loop through the cache and join EmployeeId and 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
             });
                    }
                }
            }

I am not using this query, however, this is how I can get the results using 2nd query to get managers:

 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

I'd say you should use your second SQL query to get the managers, but I'll try to speed up your code.

Problems:

  • Assuming EmployeeList is an IEnumerable , EmployeeList.ElementAt(i) is an O(n) operation, ie slow. It's a nested loop behind the scenes.
  • EmployeeList.Count() is an O(n) operation, ie slow.
  • The resulting complexity of your code is O(n^3), ie very slow.

How to improve:

  • Do one pass to build a map from EmployeeId to Employee (or whatever you store in HCache.EmployeeList ). This will enable you to find them quickly by id (in O(1)).
  • Do another pass through EmployeeList to collect the managers.
  • The overall complexity is O(n), ie proportional to the size of the EmployeeList collection.

Here is some code to illustrate the idea:

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 } }

Note that this code potentially produces duplicates in the managers list, which may or may not be what you want, but your code behaves this way so I preserved the behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM