【问题标题】:Group By Raw Data from DB按数据库中的原始数据分组
【发布时间】:2016-12-01 08:17:52
【问题描述】:

这是我来自数据库的原始数据:

PrimaryColumn   StudentId  StudentName  CourseName  CourseId  CourseDuration
     1               1           X         Cse1       C1          2
     2               1           X         Cse2       C2          1 
     3               1           X         Cse3       C3          3
     4               2           Y         Cse1       C1          2
     5               2           Y         Cse4       C4          5

来自 C# 的类结束:

public class Student 
{
  public int StudentId {get; set;}
  public string StudentName {get; set}
  public List<Course> Courses {get; set;}
}    

public class Course 
{
  public int CourseId {get; set;}
  public string CourseName {get; set;}
  public int CourseDuration {get; set; }
}

我的目标是获取按学生分组的数据以及他们将要学习的课程,这些数据是使用 List&lt;Course&gt; 作为学生类的属性来完成的。

所以,我认为这个目标非常前卫。因此,我继续对从 DB 到 C# 的原始数据使用 GroupBy,希望得到结果,但无济于事。

这是迄今为止我得到的最好的。

  masterData.GroupBy(x => new { x.StudentId, x.StudentName }, (key, group) => new { StudentId = key.StudentId, StudentName = key.StudentName, Courses=group.ToList() }).ToList();

虽然这并没有让我得到我希望得到的东西。通过发布此调用后的一些次要代码解决方法,我能够实现我所需要的。但是,每次我无法正确地对原始数据进行分组,这让我很恼火。

如果有人能向我展示进一步优化上述代码的正确方法或完全不同的方式,那将非常有帮助。

这就是我需要将结果放在List&lt;Student&gt;: 中的方式

Student:
     StudentId: 1
     StudentName: X
     List<Course> Courses: [0] - { CourseId: C1, CourseName = Cse1, CourseDuration = 2}
                           [1] - { CourseId: C2, CourseName = Cse2, CourseDuration = 1}
                           [2] - { CourseId: C3, CourseName = Cse3, CourseDuration = 3} 
Student:
     StudentId: 2
     StudentName: Y
     List<Course> Courses: [0] - { CourseId: C1, CourseName = Cse1, CourseDuration = 2}
                           [1] - { CourseId: C4, CourseName = Cse4, CourseDuration = 5}

干杯

【问题讨论】:

  • 请正确书写您的班级声明。不是公班学生,是公班学生。
  • 这不是您问题的答案,但您的表结构有问题。当课程的持续时间发生变化时会发生什么?更新表中的所有值?更好的方法是使用单独的 Student、Course 和 StudentCourses 表,请参阅 Database Normalization
  • @HebeleHododo 我同意,但这是我得到的数据,而不是我无法控制的数据库中存在的数据。

标签: c# c#-4.0 lambda generic-collections


【解决方案1】:

你可以这样做:

这里是完整的例子:dotNetFiddle

List<Student> result = data.GroupBy(x => new { x.StudentID, x.StrudentName }, 
            (key, group) => new Student{ 
                                          StudentId = key.StudentID, 
                                          StudentName = key.StrudentName,                
                                          Courses = GetCourses(group)}).ToList();

    //You can do this operation with Reflection if you want. If you don't want to write manually the property names.
    public static List<Course> GetCourses(IEnumerable<RawData> data)
    {
        List<Course> course = new List<Course>();

        foreach(var item in data)
        {
            Course c = new Course();

            c.CourseDuration = item.CourseDuration;
            c.CourseId = item.CourseID;
            c.CourseName = item.CourseName;

            course.Add(c);
        }

        return course;
    }

【讨论】:

  • 做到了!谢谢
【解决方案2】:

在你的情况下我会做的事情(但我不确定你是否会将其视为“正确分组”)类似于

var groupedStudents = masterData.GroupBy(x => x.StudentId);
foreach (var studentGroup in groupedStudents)
{
    // new studentclass
    var student = new Student(studentGroup.First().StudentId, studentGroup.First().StudentName);
    foreach (var studentRecord in studentGroup)
    {
        student.Courses.Add(new course(studentRecord.CourseId, studentRecord.CourseName, studentRecord.CourseDuration);
    }

    // add the student-object to where you want to save them i.e.
    this.MyStudentList.Add(student);
}

【讨论】:

  • 我的解决方法与此类似。不过还是谢谢。
【解决方案3】:

这里的问题是 DB 组织不善并且远离规范化状态。但是您可以将其处理为好像已正确分隔到不同的表中一样。通过这种方式,您可以提取课程、学生,然后将它们聚合 - 下面的代码应该提供线索

// get all courses
var courses = masterData.GroupBy(x => x.CourseId).Select(group => group.First())
.Select(x => new Course {CourseId = x.CourseId, CourseName = x.CourseName, ...})
.ToDictionary(x => x.CourseId);

// get all students (with empty courses for now)
var students = masterData.GroupBy(x => x.StudentId).Select(group => group.First())
.Select(x => new Student {StudentId = x.StudentId, ...})
.ToDictionary(x => x.StudentId);

// fill students with courses
foreach(var data in masterData)
{
    student[data.StudentId].Courses.Add(courses[data.CourseId]) 
}

我认为这是一种清晰的方法,可以在表规范化后重用。或者,您可以尝试编写一个复杂的 LINQ,通过一个查询来完成所有这些工作

【讨论】:

  • 哈哈。我同意,但是,DB 不是我可以控制的。感谢您的回复。
猜你喜欢
  • 2018-07-31
  • 2020-10-08
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 2017-05-31
  • 2018-08-26
相关资源
最近更新 更多