views:

351

answers:

4
+2  A: 

Here is a description how you can implement an hierarchical grouping mechanism.

A generic way of doing this using LINQ (as shown in the link) is:

var list = new List<Job>();

var groupedList = list.GroupBy(x => x.disc)
    .Select(g => new {
        Key = g.Key,
        Count = g.Count(),
        WorkCategoryGroups = g.GroupBy(x => x.workCat)
    });

However, the link also describes an alternative way which allows you to do the following:

var groupedList = list.GroupByMany(x => x.disc, x => x.workCat);

Edit: Following Ahmad's comment here is the strongly typed version:

var groupedList = list.GroupBy(x => x.disc)
    .Select(g => new Grouping {
        parent = g.Key,
        children = g.GroupBy(x => x.workCat).ToList()
    });
Obalix
I have had a look at the link and reading the comments led me to another post, so will have a look at that further. I am however, looking for a strongly typed result (Grouping)
Ahmad
Then you simply replace the `new { }` by `new StrongType { }`. And istedad of jusing `Key`, `Count`, and `WorkCategoryGroups` use your custom members. The extended approach described by the link is strongly typed.
Obalix
FYI - the posted in the above answer is great - there is a follow-up up post regarding Dynamic GroupByMany as well if anyone is interested http://blogs.msdn.com/mitsu/archive/2008/02/07/linq-groupbymany-dynamically.aspx
Ahmad
I have unmarked this as the answer - from my understanding, the selection and group by on the object yields a unique result for each combination. eg even though i can have two jobs with the same Discipline and unique Workcatergory - the result will yield me two groups. I think this is due to the comparisons being made on reference type objects.
Ahmad
@Ahmad: When answering your questions, I can only go from the information you provided. Your solution, is nearly identical to mine - except the extended grouping - so it lead you to the right answer. Taking the reward away is, IMHO, not nice, except if some other answer (not by your self) provided the correct conlusion from the information you have given. Othewise, every poster would add a final post and accept her/his own solution, thus denying the reward to the people who spent their time leading them to the final solution.
Obalix
I must apologize if it seems that way. The difference of your answer to me is actually quite great. All the responses posted including yours led to the same result which is not the one i was looking for. Looking at the initial solution i was posted, is however far more similar to my solution. The problem as noted is with regards to the grouping of reference types and objects (which is a similar theme of almost all answers posted). If you want your solution re-marked as the correct answer, no problem..edit - i remarked it as correct
Ahmad
+2  A: 

I'd use Linq syntax:

var jobsByDiscipline = 
    from j in repository.GetJobsWithActiveStatus()
    group j by j.Discipline.DisciplineID into g
    select new { 
        DisciplineID = g.Key,
        Jobs = g.ToList() 
    };

var jobsByCategory = 
    from j in repository.GetJobsWithActiveStatus()
    group j by j.Workcategory.WorkcategoryID into g
    select new { 
        WorkcategoryID = g.Key,
        Jobs = g.ToList() 
    };

I find that easier to read than lots of chained methods with lambda-function parameters.

You can get your groupings from this:

var disciplineAndCategory = 
    from j in repository.GetJobsWithActiveStatus()
    group j by j.Discipline.DisciplineID into g
    let categories = 
        from j2 in g
        select j2.Workcategory.WorkcategoryID
    select new { 
        DisciplineID = g.Key,
        Jobs = categories.Distinct() // each category id once 
    };
Keith
+1 Agreed, this syntax is **much** easier to read when doing grouping.
Nick Craver
@keith, thanks for the suggestion, my first attempt using it seemed to work - however it was not tested, however I prefer the chained methods approach - personal preference I guess :)
Ahmad
A: 

Here's another way that doesn't require the Grouping class.

ILookup<Discipline, Workcategory> result = repository
  .GetJobsWithActiveStatus()
  .Select(job => new {disc = job.disc, workCat = job.workCat})
  .Distinct()
  .ToLookup(x => x.disc, x => x.workCat);
David B
After testing this, it yields a similar result to Obalix's answer. A grouping for each discipline and workcategory
Ahmad
A: 

This is the solution that works for me.

I first needed to get all discipline groups, then create the associated workcategory lists where the disciplineID are equal.

var result = liveJobs
.GroupBy(x => new {
               x.disc.DisciplineID, 
               x.disc.DisciplineName
                  })
.Select(g => new Grouping()
              {
               parent = new Discipline(g.Key.DisciplineID,g.Key.DisciplineName),
               children = g.Where(job=>job.disc.DisciplineID == g.Key.DisciplineID) // filter the current job discipline to where the group key disciplines are equal
              .Select(j=>j.workCat)
              .ToList()
              });
Ahmad