【问题标题】:Get data from DataTable to class with list使用列表从 DataTable 获取数据到类
【发布时间】:2021-04-08 08:10:03
【问题描述】:

我需要从 DataTable 中获取数据以填充如下对象:

public class StudentModel
{
    public int IdStudent { get; set; }
}

public class ClassRoomModel
{
    public List<StudentModel> Students { get; set; } = new List<StudentModel>();
    public int IdClassRoom { get; set; }
    public string ClassRoom { get; set; }
}  

我的 DataTable 返回这些数据:

ClassRoom IdClassRoom IdStudent
A 1 1001
A 1 1002
A 1 1003
B 2 2001
B 2 2002
B 2 2003

我如何区分或按教室与相关学生分组?

提前谢谢你

【问题讨论】:

  • 您是如何获得DataTable 的?如果您从 SQL 查询中获取它,您需要 DataTable 吗?
  • 是的,我从 SQL 查询中获取 DataTable

标签: c# .net linq


【解决方案1】:
List<ClassRoomModel> classes = table.AsEnumerable()
    .GroupBy(r => (ClassRoom:r.Field<string>("ClassRoom"),IdClassRoom:r.Field<int>("IdClassRoom")))
    .Select(g => new ClassRoomModel
    {
        ClassRoom = g.Key.ClassRoom,
        IdClassRoom = g.Key.IdClassRoom,
        Students = g.Select(r => new StudentModel{ IdStudent = r.Field<int>("IdStudent") }).ToList()
    })
    .ToList();

因为 Jochem 在评论中询问如何使用 GroupBy 中的 resultSelector 参数来做到这一点:

List<ClassRoomModel> classes = table.AsEnumerable()
    .GroupBy(
        r => (ClassRoom: r.Field<string>("ClassRoom"), IdClassRoom: r.Field<int>("IdClassRoom")), 
        r => new StudentModel { IdStudent = r.Field<int>("IdStudent")}
    )
    .Select(studentsGroup => new ClassRoomModel
    {
        ClassRoom = studentsGroup.Key.ClassRoom,
        IdClassRoom = studentsGroup.Key.IdClassRoom,
        Students = studentsGroup.ToList()
    })
    .ToList();

我个人更喜欢第一个版本。

【讨论】:

  • 好的,但我必须修改 groub,例如: .GroupBy(r => new { ClassRoom = r.Field("ClassRoom"),IdClassRoom = r.Field("IdClassRoom") })
  • @R1g3L:您不使用当前的 .NET 框架? ValueTuples 从 C#7 开始就存在
  • 是的,抱歉,可能是因为我使用的是 .NET 4.5
  • @R1g3L: 那么你应该从 nuget 下载 System.ValueTuple: nuget.org/packages/System.ValueTuple 但是是的,你也可以使用匿名类型。与元组相比,它们的开销很小
  • 可能有点跑题了,但是使用 select 映射分组数据和 group by 函数的第三个参数有什么区别吗? GroupBy,结果选择器
【解决方案2】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("ClassRoom", typeof(string));
            dt.Columns.Add("IdClassRoom", typeof(int));
            dt.Columns.Add("IdStudent", typeof(int));

            dt.Rows.Add(new object[] {"A", 1, 1001});
            dt.Rows.Add(new object[] {"A", 1, 1002});
            dt.Rows.Add(new object[] {"A", 1, 1003});
            dt.Rows.Add(new object[] {"B", 2, 2001});
            dt.Rows.Add(new object[] {"B", 2, 2002});
            dt.Rows.Add(new object[] {"B", 2, 2003});

            List<ClassRoomModel> rooms = dt.AsEnumerable()
                .GroupBy(x => x.Field<int>("IdClassRoom"))
                .Select(x => new ClassRoomModel() {
                    IdClassRoom = x.Key,
                    ClassRoom = x.FirstOrDefault().Field<string>("ClassRoom"),
                    Students = x.Select(y => new StudentModel() { IdStudent = y.Field<int>("IdStudent")}).ToList()
                }).ToList();
        }
    }
    public class StudentModel
    {
        public int IdStudent { get; set; }
    }

    public class ClassRoomModel
    {
        public List<StudentModel> Students { get; set; }
        public int IdClassRoom { get; set; }
        public string ClassRoom { get; set; }
    }  
}

【讨论】:

  • 您可以对多个字段进行分组
【解决方案3】:

如果您使用 SqlCommandSqlDataReader 从 SQL 查询加载学生,则不需要中间的 DataTable 步骤。您可以使用阅读器简单地加载它们:

Dictionary<int, ClassRoomModel> models = new Dictionary<int, ClassRoomModel>();
List<ClassRoomModel> classroomModels = new List<ClassRoomModel>();
using (SqlCommand command = new SqlCommand("SELECT ClassRoom, IdClassRoom, IdStudent FROM ClassroomStudentView", conn)) // whatever your real query is

using (SqlDataReader reader = command.ExecuteReader())
{
    // this will return `true` until there aren't any results from the query
    while (reader.Read())
    {
        // get the classroom id and check if we need to create a new model for it
        // (i.e. it doesn't currently exist in the dictionary)
        int classRoomId = (int)reader["IdClassRoom"];
        if (!(models.TryGetValue(classRoomId, out ClassRoomModel model)))
        {
            // read the classroom name and create the new model
            string classRoom = (string)reader["ClassRoom"];
            model = new ClassRoomModel() { IdClassRoom = classRoomId, ClassRoom = classRoom, Students = new List<StudentModel>() };
            // put it in the classrooms dictionary ("models")
            models[classRoomId] = model;
            // add the same in-memory object to the list for our final result
            classroomModels.Add(model);
        }

        // add the current student to the classroom model's students list
        int studentId = (int)reader["IdStudent"];
        model.Students.Add(new StudentModel() { IdStudent = studentId });
    }
}

// Now you have `classroomModels` populated with the grouped classroom objects.

【讨论】:

    猜你喜欢
    • 2020-10-13
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 2020-10-01
    相关资源
    最近更新 更多