Question

I have the following classes:

public class Student
{
    public string StudentID { get; set; }
    public string StudentName { get; set; }
}
public class Marks
{
    public string StudentID { get; set; }
    public string SubjectName { get; set; }
    public string Score { get; set; }
} 

Populating the collection:

Collection<Student> objStudentCollection = new Collection<Student>();
Student student = new Student();
student.StudentID = "104517";
student.StudentName = "John";
objStudentCollection.Add(student);

student = new Student();
student.StudentID = "104520";
student.StudentName = "Stella";
objStudentCollection.Add(student);

Collection<Marks> objMarkCollection = new Collection<Marks>();
Marks marks = new Marks();
marks.StudentID = "104517";
marks.SubjectName = "English";
marks.Score = "85";
objMarkCollection.Add(marks);

marks = new Marks();
marks.StudentID = "104517";
marks.SubjectName = "Science";
marks.Score = "60";
objMarkCollection.Add(marks);


marks = new Marks();
marks.StudentID = "104517";
marks.SubjectName = "Mathematics";
marks.Score = "75";
objMarkCollection.Add(marks);


marks = new Marks();
marks.StudentID = "104517";
marks.SubjectName = "Optional 1";
marks.Score = "75";
objMarkCollection.Add(marks);


marks = new Marks();
marks.StudentID = "104520";
marks.SubjectName = "French";
marks.Score = "54";
objMarkCollection.Add(marks);

marks = new Marks();
marks.StudentID = "104520";
marks.SubjectName = "Science";
marks.Score = "60";
objMarkCollection.Add(marks);


marks = new Marks();
marks.StudentID = "104520";
marks.SubjectName = "Mathematics";
marks.Score = "75";
objMarkCollection.Add(marks);


marks = new Marks();
marks.StudentID = "104520";
marks.SubjectName = "Optional 1";
marks.Score = "50";
objMarkCollection.Add(marks);

I would like to bind the above collections in GridView to display like:

StudentID | StudentName | English | French | Mathematics | Science | Optional 1 | Total

Was it helpful?

Solution

I think you need to utilise the GroupJoin method to get what you're after. You could do it like this if the list of subjects if fixed and not going to change:

var q = 
  objStudentCollection
  .GroupJoin(
    objMarkCollection,
    stu => stu.StudentID,
    mark => mark.StudentID,
    (stu, mark) =>
        new
        {
            student.StudentID,
            student.StudentName,
            English = mark.Where(m => m.SubjectName == "English").Sum(m => Convert.ToInt32(m.Score)),
            French  = mark.Where(m => m.SubjectName == "French").Sum(m => Convert.ToInt32(m.Score)),
            Mathematics  = mark.Where(m => m.SubjectName == "Mathematics").Sum(m => Convert.ToInt32(m.Score)),
            Science   = mark.Where(m => m.SubjectName == "Science").Sum(m => Convert.ToInt32(m.Score)),
            Optional1  = mark.Where(m => m.SubjectName == "Optional 1").Sum(m => Convert.ToInt32(m.Score)),
            Total = mark.Sum(m => Convert.ToInt32(m.Score)),
        })

It's not the prettiest code in the world, but it will give you an anonymous type with each row containing data you asked for. You could replace Sum with SingleOrDefault if there is only ever one mark per subject.

var subjects = 
    objMarkCollection
    .Select(mark => mark.SubjectName)
    .Distinct()
    .Dump();

var q =  
    objStudentCollection 
    .GroupJoin( 
        objMarkCollection, 
        stu => stu.StudentID, 
        mark => mark.StudentID, 
        (stu, mark) => 
            new 
            { 
                student.StudentID, 
                student.StudentName, 
                Marks = 
                    from s in subjects
                    join m in mark on s equals m.SubjectName into outer
                    from o in outer.DefaultIfEmpty()
                    select new
                    {
                        SubjectName = s,
                        Score = (o == null) ? 0 : Convert.ToInt32(o.Score),
                    },
                Total = mark.Sum(m => Convert.ToInt32(m.Score)), 
            }) 
    .Dump();

This 2nd solution will create you an anonymous type with each student and a collection of marks including each subject (those the student has not take will have a 0 score).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top