Рассмотрите следующие упрощенные объекты и отношения:
public class Job{
int JobId;
String name;
String status;
Discipline disc;
WorkCategory workCat;
}
public class Discipline {
int DisciplineId;
String DisciplineName;
}
public class Workcategory{
int WorkCategoryId;
String WorkCategoryName;
}
public Class Grouping{
Discipline parent;
List<Workcategory> children;
}
Вышеупомянутые модели отношения это a Job
связан с одним Discipline
и один WorkCategory
. Workcategory
всегда ребенок определенного родителя Discipline
(связь "один ко многим"). Мы можем предположить, что отношения присвоенного Discipline и Workcategory всегда будут допустимы.
Проблема, с которой я сталкиваюсь, - когда я пытаюсь создать a Grouping
объект результата на основе фильтров, к которым относятся Jobs
. Я не уверен, Может ли это быть сделано или если подход, который я проявляю, даже корректен. Сам точный вопрос не ясен мне, однако вышеупомянутое определяет проблемный оператор.
Grouping
класс?Я попробовал следующее (это - мое первое использование попытки Linq), но ни к какому успеху, поскольку мое понимание не достаточно полно. Другая альтернатива должна сначала добраться Discipline
группа и цикл посредством исходной группировки, берущей связанное Workcategory
.
var grouping = repository.GetJobsWithActiveStatus()
.GroupBy(x => new {
x.Discipline.DisciplineID,
x.Discipline.DisciplineName,
x.Category.WorkCategoryID,
x.Category.WorkCategoryName
})
.Select(g => new Grouping{
Discipline = new Discipline{
DisciplineID = g.Key.DisciplineID,
Name = g.Key.DisciplineName
},
Categories = ?? // this is where I am lost
}});
Править: Отправив это, я понял, что параметры inital GroupBy приводят к одной группе объекта, тогда как я ищу результат Подгруппы Группы.
Редактирование 2: Для разъяснения немного далее я не хочу связанного Jobs как часть результата, а скорее группировку Дисциплины-Workcategory - таким образом причина Grouping
класс
Начальное решение на основе @Obalix
Редактирование 7 марта 2010:
Это решение не работает - GroupBy на объектной Дисциплине приведет к уникальной группировке для каждого объекта. Я думаю, что это происходит из-за него являющийся ссылочным типом. Я корректен? Я первоначально принял это как ответ, однако после того, как некоторое царапание головы поняло, что мои ложные данные сами были дефектными. Начальные вопросы все еще остаются отвеченными.
var result = repository.GetJobsWithActiveStatus()
.GroupBy(x => x.disc)
.Select(g => new Grouping
{
Discipline = g.Key,
Catergories = g.GroupBy(x=>x.workCat) // <--- The Problem is here, grouping on a reference type
.Select(l=>l.Key) // needed to select the Key's only
.ToList()
});
Вот описание того, как можно реализовать механизм иерархического группирования.
Общий способ сделать это с помощью LINQ (как показано в ссылке):
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)
});
Однако ссылка также описывает альтернативный способ, который позволяет вам сделать следующее:
var groupedList = list.GroupByMany(x => x.disc, x => x.workCat);
Изменить: Следуя указаниям Ахмада комментарий здесь - строго типизированная версия:
var groupedList = list.GroupBy(x => x.disc)
.Select(g => new Grouping {
parent = g.Key,
children = g.GroupBy(x => x.workCat).ToList()
});
Вот еще один способ, который не требует класса группирования.
ILookup<Discipline, Workcategory> result = repository
.GetJobsWithActiveStatus()
.Select(job => new {disc = job.disc, workCat = job.workCat})
.Distinct()
.ToLookup(x => x.disc, x => x.workCat);
Я бы использовал синтаксис Linq:
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()
};
Я считаю это легче читать, чем множество связанных методов с параметрами лямбда-функции.
Вы можете получить свои группы из этого:
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
};
Вот решение, которое работает для меня.
Сначала мне нужно было получить все группы дисциплин, затем создать связанные списки рабочих категорий. где идентификаторы дисциплин равны.
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()
});