简体   繁体   中英

Create inversed datatable from object list

I have ClassGrades table that has the following fields:
Id, ClassId, Student, Match, Science, History, English

I retrieve all of the correct rows using a function such as the following:

IList<ClassGrade> classGrades = ClassService.GetClassGrades(classId: 1);

This list will have ClassGrade objects in it that look like this:
Id=1, ClassId=1, Student='Mark', Math=50.6, Science=21.8, History=70.7, English=80.1
Id=2, ClassId=1, Student='Jacob', Math=70.8, Science=19.4, History=78.7, English=11.1
Id=3, ClassId=1, Student='Lauren', Math=21.9, Science=61.1, History=99.5, English=12.1
Id=4, ClassId=1, Student='Sarah', Math=81.7, Science=65.2, History=73.7, English=65.1

I need to flip these results so that the students are the columns and the subjects w/ grades are the rows and then bind it to a Grid on my page. I figured creating a new datatable and customizing it as necessary would be the best way to do this.

DataTable dt = new DataTable();

In the end my grid needs to look something like this:

            Mark    Jacob   Lauren   Sarah  
Math        50.6    70.8    21.9     81.7  
Science     21.8    19.4    61.1     65.2  
History     70.7    78.7    99.5     73.7  
English     80.1    11.1    12.1     65.1 

Can someone give me an example of how I would take the object list of ClassGrades and dynamically create a datatable that resembles the above. I would prefer using linq when possible. Also, if doing this completely in sql is the preferred way I am fine with that too, but an example would be nice.

A couple of things to note:

  • The Subjects will only ever be those 4.
  • The Students can be any random amount depending on how many Students are in a class.
  • For each student within a class a row is returned.

Below is an example of where I am getting stuck:

// retrieve object list
IList<ClassGrade> classGrades = ClassService.GetClassGrades(classId: 1);

// create datatable
DataTable dt = new DataTable();

// get list of students
var students = from s in classGrades
               select s.Student

// get list of subjects
IList<string> subjects = new List<string>() { "Math", "Science", "History", "English" };

// create columns
table.Columns.Add(subject, typeof(string));
foreach (var student in students)
{
    table.Columns.Add(student, typeof(double));
}

// create rows
foreach (var subject in subjects) 
{
    row = dt.NewRow();
    row[subject] = subject;

    foreach (var classGrade in classGrades)
    {
        // this is where I get stuck
        row[classGrade.Student] = 
    }
}

Tested in LinqPad. See the attached picture for result.

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

namespace PivotDataTable
{
    class Program
    {
        public static object GetPropValue(object src, string propName)
        {
            return src.GetType().GetProperty(propName).GetValue(src, null);
        }

        static void Main()
        {
            // retrieve object list
            var classGrades = new List<ClassGrades>() {
                new ClassGrades() {Id=1, ClassId=1, Student="Mark", Math=50.6, Science=21.8, History=70.7, English=80.1},
                new ClassGrades() {Id=2, ClassId=1, Student="Jacob", Math=70.8, Science=19.4, History=78.7, English=11.1},
                new ClassGrades() {Id=3, ClassId=1, Student="Lauren", Math=21.9, Science=61.1, History=99.5, English=12.1},
                new ClassGrades() {Id=4, ClassId=1, Student="Sarah", Math=81.7, Science=65.2, History=73.7, English=65.1}
            };

            // create datatable
            DataTable dt = new DataTable();

            // get list of students
            var students = from s in classGrades
                select s.Student;

            // get list of subjects
            var subjects = new List<string>() { "Math", "Science", "History", "English" };

            // create columns
            dt.Columns.Add("subject", typeof(string));
            foreach (var student in students)
            {
                dt.Columns.Add(student, typeof(double));
            }

            // create rows
            foreach (var subject in subjects)
            {
                var row = dt.NewRow();
                row[0] = subject;

                foreach (var classGrade in classGrades)
                {
                    row[classGrade.Student] = Convert.ToDouble(GetPropValue(classGrade, subject));
                }

                // add row to data table
                dt.Rows.Add(row);
            }

            Console.Write("Press any key to continue . . . ");
            // to see the result in LinqPad: remark the ReadKey line, unremark the Dump line
            Console.ReadKey(true);
            //dt.Dump();
        }
    }

    class ClassGrades
    {
        public int Id { get; set; }
        public int ClassId { get; set; }
        public string Student { get; set; }
        public double Math { get; set; }
        public double Science { get; set; }
        public double History { get; set; }
        public double English { get; set; }
    }
}

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM