tags:

views:

145

answers:

2

I am trying to get into LINQ to objects as I can see the power of it. Lucky enough I have a question that I think LINQ should be able to solve.

Here is the question (the details are an example);

public class SchoolClass
{
    public int ID;
    public string Name;
    public string Teacher;
    public string RoomName;

    public string Student_Name;
    public int Student_Age;
}

As you can see by the example, there is a one to many relationship between the ClassName, Teacher and Room and the Students, i.e. there are potentially many students in the one class.

If we have a List is it possible using LINQ to create a List but have only one instance ID, Name, Teacher, RoomName and an ArrayList of Student_Name and Age?

Producing this:

public class Students
{
    public string Student_Name;
    public int Student_Age;
}

public class SchoolClass
{
    public int ID;
    public string Name;
    public string Teacher;
    public string RoomName;

    public ArrayList Students;
}

Essentially, using LINQ to clean the List to a more logical structure?

To give some background to this example. The second structure is used by a DataGrid to produce a Master-Child relationship. We store SchoolClass and StudentInformation in classes as shown above. It would be good use of LINQ to be able to convert our initial List into a structure which can be used by the DataGrid.

+6  A: 

I changed the ArrayList to List<Students>, and:

    List<SourceData> source = new List<SourceData>();
    //...your data here ;-p
    var classes = (from row in source
                  group row by new {
                          row.ID, row.Name,
                          row.Teacher, row.RoomName }
                      into grp
                      select new SchoolClass
                      {
                          ID = grp.Key.ID,
                          Name = grp.Key.Name,
                          Teacher = grp.Key.Teacher,
                          RoomName = grp.Key.RoomName,
                          Students = new List<Students>(
                              from row in grp
                              select new Students
                              {
                                  Student_Age = row.Student_Age,
                                  Student_Name = row.Student_Name
                              })
                      }).ToList();
Marc Gravell
i can use this .. thanks
Fleming
what if the SchoolClass had additional properties which were not needed for the grouping but should be present in the final result List. i.e. TeacherFirstName, TeacherLastName etc ... grouping on just a few properties is enough.
Fleming
Well, which would you choose (there could be multiple different hits). But in that case, you could use: Teacher = grp.Select(x=>x.Teacher).First()
Marc Gravell
there will not be multiple Teachers for SchoolClass, only one per class no need to worry about First(). Question was related to having many properties in SchoolClass which will only appear once.
Fleming
Do I have to list every property in the group clause and then again in the select statement. This make maintaining the LINQ cumbersome if new properties are added to SchoolClass ... excellent help so far
Fleming
An alternative is to (after "into grp") add "let first = grp.First()", then you can use first.Teacher etc
Marc Gravell
If the original data is rectangular, then there *will* be multiple "teacher" values per group; re the "group" - that all defines on what uniquely identifies the class. If you are confident that the other values won't change, then use the first.Whatever trick
Marc Gravell
+1  A: 

If I'm understanding this correctly, I would've thought the best way to implement the SchoolClass class would be to create a Student class (probably a LINQ-to-SQL entity, if you're using it) and to have a generic list of type student, something similar to this:

public class SchoolClass
{    
    public int ID;    
    public string Name;    
    public string Teacher;    
    public string RoomName;    
    public List<Student> Students;
}

The list of students could then be populated using a linq query, although I'm not sure exactly how without more information.

Hope this is some help.

Lee D
lets just assume that List<SchoolClass> may contain 50 SchoolClass and we just need to put all the Student information into a subList so that we have one SchoolClass and an ArrayList for Students 50 deep.
Fleming