将IDataRecord个别记录分组到集合

时间:2013-12-20 08:12:36

标签: c# linq generics ado.net

我在数据库中有如下列出的数据。

enter image description here

我有以下适用于简单场景的数据访问层代码。但对于上述场景,我需要基于employeeID grouping的结果。员工的所有角色都应该在一个Employee对象下。

我们如何通过使用C#的通用委托功能修改以下数据访问代码来实现这一目标?

注意:我正在寻找一种不使用DataTable的解决方案(因为DataTable预先加载所有数据并且比IDataRecord方法慢)。

参考

  1. An Elegant C# Data Access Layer using the Template Pattern and Generics
  2. Using C# generics and factory classes to map IDataReader to POCO
  3. 数据传输对象

    public class Role
    {
        public int RoleID { get; set; }
        public string RoleName { get; set; }
    }
    
    
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public List<Role> Roles { get; set; }
    
        //IDataRecord Provides access to the column values within each row for a DataReader
        //IDataRecord is implemented by .NET Framework data providers that access relational databases.
    
        //Factory Method
        public static Employee EmployeeFactory(IDataRecord record)
        {
            return new Employee
            {
                EmployeeID = (int)record[0],
                EmployeeName = (string)record[1]
            };
        }
    }
    

    普通DAL

    public class MyCommonDAL
    {
        public static IEnumerable<T> ExecuteQueryGenericApproach<T>(string commandText, List<SqlParameter> commandParameters, Func<IDataRecord, T> factoryMethod)
        {
            string connectionString = @"Server=TRVMVSDDVXXXX;Database=AS400_Source;User Id=XXXXXXXX;Password=XXXXXXX";
    
            //Action, Func and Predicate are pre-defined Generic delegates.
            //So as delegate they can point to functions with specified signature.
    
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;
                    command.CommandType = CommandType.Text;
                    command.CommandText = commandText;
                    command.CommandTimeout = 0;
                    command.Parameters.AddRange(commandParameters.ToArray());
    
                    connection.Open();
                    using (var rdr = command.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            yield return factoryMethod(rdr);
                        }
                        rdr.Close();
                    }
                }
            }
        }
    }
    

    特定DAL

    public class MyEmployeeDAL
    {
        public List<Employee> GetEmployees(string excludedEmployee)
        {
    
    
            List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                    {
                                                        new SqlParameter {ParameterName = "@ExcludedEmployee", 
                                                                          Value = excludedEmployee, 
                                                                          SqlDbType = SqlDbType.VarChar}
                                                    };
    
    
            string commandText = @"SELECT E.EmployeeID,E.EmployeeName,R.RoleID,R.RoleName FROM dbo.EmployeeRole ER
                                    INNER JOIN dbo.Employee E  ON E.EmployeeID= ER.EmployeeID
                                    INNER JOIN dbo.[Role] R ON R.RoleID= Er.RoleID 
                                    WHERE EmployeeName <> @ExcludedEmployee";
    
            IEnumerable<Employee> employees = MyCommonDAL.ExecuteQueryGenericApproach<Employee>(commandText, commandParameters, Employee.EmployeeFactory);
            return employees.ToList();
        }
    }
    

    客户端

        static void Main(string[] args)
        {
            MyEmployeeDAL logDAL = new MyEmployeeDAL();
            List<Employee> logSeverities = logDAL.GetEmployees("test");
        }
    

3 个答案:

答案 0 :(得分:2)

你应该添加新的平面类

public class RoleAndEmployee
{
    public int RoleID { get; set; }
    public string RoleName { get; set; }
    public int EmployeeID { get; set; }
    public string EmployeeName { get; set; }

    public static Employee EmployeeFactory(IDataRecord record)
    {
        return new RoleAndEmployee
        {
            EmployeeID = (int)record[0],
            EmployeeName = (string)record[1],
            RoleID = (int)record[2],
            RoleName = (string)record[3]
        };
    }
}

并打电话(我希望,没有IDE我写得正确):

IEnumerable<Employee> employees = MyCommonDAL.ExecuteQueryGenericApproach<RoleAndEmployee>(commandText, commandParameters, RoleAndEmployee.EmployeeFactory)
    .GroupBy(c=>new {c.EmployeeId, c.EmployeeName}, c=>new{c.RoleId, c.RoleName})
    .Select(k=>new Employee{EmployeeId=k.Key.EmployeeId, EmployeeName= k.Key.EmployeeName, Roles = k.ToList()});

<强>更新 如果你不想引入平面类,你可以使用下一个方法:

public static Employee EmployeeFactory(IDataRecord record)
{
    var employee = new Employee
    {
        EmployeeID = (int)record[0],
        EmployeeName = (string)record[1],
        Roles = new List<Role>()
    };
    employee.Roles.Add(new Role{RoleID = (int)record[2], roleName=(string)record[3]});
    return employee;
}

IEnumerable<Employee> employees = MyCommonDAL.ExecuteQueryGenericApproach
    <Employee>(commandText, commandParameters, Employee.EmployeeFactory)
        .GroupBy(
            x => new { x.EmployeeID, x.EmployeeName},
            (key, group) => 
                new Employee
                    {
                        EmployeeId=key.EmployeeID, 
                        EmployeeName=key.EmployeeName,
                        Roles = group.SelectMany(v => v.Roles).ToList()
                    }).ToList();

答案 1 :(得分:0)

为此,您需要为Roles个对象的Employee属性分配值。

在factoryMethod中,您需要找到不同的员工创建相同的对象,并分配从查询中获得的相应角色。

This可以帮助您查询您的表格。

答案 2 :(得分:0)

在您的特定DAL中执行logDAL.GetEmployees("test")后,只需将它们分组。

IEnumerable<Employee> employees = MyCommonDAL.ExecuteQueryGenericApproach
        <Employee>(commandText, commandParameters, Employee.EmployeeFactory);
employees = employees.GroupBy(
                x => new
                    {
                        x.EmployeeID, 
                        x.EmployeeName
                    },
                (key, groupedEmployees) => 
                    new Employee
                        {
                            EmployeeId=key.EmployeeID, 
                            EmployeeName=key.EmployeeName,
                            Roles = groupedEmployees.SelectMany(v => v.Roles)
                        });
return employees.ToList();