从树结构中的数据库中获取记录

时间:2017-08-12 20:49:43

标签: c# sql-server linq

我正在尝试从数据库中获取记录。

我的数据库表:

  1. 部门
  2. 员工部门(部门中级表--->员工)
  3. 员工
  4. EmployeeLocations (员工中间表--->地点)
  5. 位置
  6. 上表包含大量记录。

    我的数据将根据以下结构生成:

    enter image description here

    我尝试了什么:

    我的第一个方法:

    //Get all the departments
    List<Department> departmentList = sp.GetAllDeparments();
    
    //Get all employees
    List<Employee> employeeList= sp.GetAllEmployees();
    
    //Get all locations
     List<Location> locationList= sp.GetAllLocations();
    
    //Get EmployeeLocations List<EmployeeLocations> emplocationList= 
     sp.GetAllEmployeeLocations();
    
    //Get EmployeeDepartments List<EmployeeDepartments> empDepList= 
    sp.GetAllEmployeeDepartments();
    
    foreach(Deparment deparment in departmentList){
    
        foreach(Employee employee in employeeList){
    
            foreach(Location location in locationList){
    
            }
        }
    }
    

    如果我在foreach循环中点击数据库,上面的代码大约需要6分钟。

    我的第二种方法:

    {{1}}

    我从所有上述表中获取所有记录,并在foreach代码中使用LINQ进行操作。因此,将时间从6分钟缩短到4分钟。

    我的问题: 在尽可能短的时间内获取数据的有效方法是什么。在这种情况下?

    我需要在上图中操作数据。

2 个答案:

答案 0 :(得分:1)

涉及较少数据库往返的第二种方法要好得多。但根据你的评论

  

即使我目前正在使用第二种方法,一次获取数据并将其保存在内存中也不是问题。但是在做foreach时我正在使用LambdaExpression进行提取。这需要时间。

看起来您的处理部分正在使用大量低效的线性搜索。通过准备和使用基于快速哈希的查找数据结构,可以显着改善它。

在这种特殊情况下,您需要两个dictionaries来快速定位员工PK和PK定位,两个lookups用于按部门PK快速定位员工,按员工PK定位员工。

假设您的类模型是这样的(您可以使用实际的属性名称/类型对其进行修改):

class Department
{
    public int Id { get; set; } // PK
    // Other properties...
}

class Employee
{
    public int Id { get; set; } // PK
    // Other properties...
}

class Location
{
    public int Id { get; set; } // PK
    // Other properties...
}

class EmployeeDepartment
{
    public int EmployeeId { get; set; } // FK
    public int DepartmentId { get; set; } // FK
}

class EmployeeLocation
{
    public int EmployeeId { get; set; } // FK
    public int LocationId { get; set; } // FK
}

然后处理可能是这样的:

//Fetch all necessary data
List<Department> departmentList = sp.GetAllDeparments();    
List<Employee> employeeList = sp.GetAllEmployees();
List<Location> locationList = sp.GetAllLocations();
List<EmployeeLocation> employeeLocationList = sp.GetAllEmployeeLocations();
List<EmployeeDepartment> employeeDepartmentList = sp.GetAllEmployeeDepartments();

// Build the helper fast lookup structures
var employeeById = employeeList.ToDictionary(e => e.Id);
var locationById = locationList.ToDictionary(e => e.Id);
var employeesByDepartmentId = employeeDepartmentList.ToLookup(e => e.DepartmentId, e => employeeById[e.EmployeeId]);
var locationsByEmployeeId = employeeLocationList.ToLookup(e => e.EmployeeId, e => locationById[e.LocationId]);

// The processing
foreach (Department deparment in departmentList)
{
    foreach (Employee employee in employeesByDepartmentId[deparment.Id])
    {
        foreach (Location location in locationsByEmployeeId[employee.Id])
        {

        }
    }
}

答案 1 :(得分:0)

问题&amp;建议;

  

如果在接收数据时重复打开sql连接   从列表中,只需要一个数据库请求。你需要   列出该请求中多次出现的列表

     

结果:请求应该发送到数据库一次。我摔倒   使用字典方法检索列表,然后15%   实现了性能提升。如果你的工作真的很大   数据,你可以异步工作

如果需要更多细节,我们需要查看以get开头的函数的内容。