【问题标题】:C# Linq or querying IEnumerableC# Linq 或查询 IEnumerable
【发布时间】:2019-06-09 00:00:31
【问题描述】:

我有一个员工表,其中还包含部门经理信息。我需要填充两个下拉列表 - 一个包含员工,另一个包含经理。我不是使用两个查询来拉员工,另一个查询来拉经理,而是查询表一次并将所有信息存储在缓存中的 IEnumerable EmployeeList 中。

我需要一些查询来从该查询中提取管理器 - 使用 LINQ 或在 C# 代码中循环。我写了循环,但是效率很低。

这是填充 HCache 的 SQL 查询:

    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

【问题讨论】:

  • 如果DTO.Employee类有一个属性DTO.Employee Manager不是更好吗?然后,您可以在链向上链接后向上导航。同样,该类将具有List&lt;DTO.Employee&gt; DirectReports
  • 我正在尝试为下拉列表拉出两个单独的列表 - 包含员工信息和经理信息。我可以轻松地从缓存中提取员工信息。这里的问题是 manager 的循环是永远的。请建议是否有更好的方法来优化代码。

标签: c# linq for-loop inner-join ienumerable


【解决方案1】:

我会说您应该使用第二个 SQL 查询来获取管理器,但我会尝试加快您的代码速度。

问题:

  • 假设EmployeeListIEnumerableEmployeeList.ElementAt(i) 是 O(n) 操作,即慢。这是幕后的嵌套循环。
  • EmployeeList.Count() 是一个 O(n) 操作,即慢。
  • 由此产生的代码复杂度为 O(n^3),即非常慢。

如何改进:

  • 执行一次以构建从EmployeeIdEmployee(或您存储在HCache.EmployeeList 中的任何内容)的地图。这将使您能够通过 id 快速找到它们(在 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 列表中产生重复项,这可能是也可能不是您想要的,但您的代码会以这种方式运行,因此我保留了该行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多