Поскольку вы объединяете записи вместе, это утверждение неверно:
Теперь этот набор результатов будет иметь только ОДНУ ProcessBases, каждая ProcessBase
будет иметь НЕСКОЛЬКО инспекторов статей, и каждый инспектор статей будет
есть несколько образцов инспектора.
На самом деле после выполнения запроса вы получите IEnumerable
, где каждый объект в IEnumerable
содержит ссылку на ProcessBase
, InspectorArticle
и InspectorSample
. Например, использование приведенного ниже кода в LinqPad приведет к IEnumerable
со следующим содержимым:
Код:
void Main()
{
var processBases = new List<ProcessBase>();
var inspectorArticles = new List<InspectorArticle>();
var inspectorSamples = new List<InspectorSample>();
processBases.Add(new ProcessBase { ID = 1 });
processBases.Add(new ProcessBase { ID = 2 });
inspectorArticles.Add(new InspectorArticle { ID = 3, ProcessBaseID = 1 });
inspectorArticles.Add(new InspectorArticle { ID = 4, ProcessBaseID = 1 });
inspectorArticles.Add(new InspectorArticle { ID = 5, ProcessBaseID = 2 });
inspectorSamples.Add(new InspectorSample { ID = 6, InspectorArticleID = 3 });
inspectorSamples.Add(new InspectorSample { ID = 7, InspectorArticleID = 3 });
inspectorSamples.Add(new InspectorSample { ID = 8, InspectorArticleID = 3 });
inspectorSamples.Add(new InspectorSample { ID = 9, InspectorArticleID = 4 });
inspectorSamples.Add(new InspectorSample { ID = 10, InspectorArticleID = 5 });
inspectorSamples.Add(new InspectorSample { ID = 11, InspectorArticleID = 5 });
var processBaseID = 1;
var results = from obj1 in processBases
join obj2 in inspectorArticles on obj1.ID equals obj2.ProcessBaseID
join obj3 in inspectorSamples on obj2.ID equals obj3.InspectorArticleID
where obj1.ID == processBaseID
select new { obj1, obj2, obj3 };
Console.WriteLine(results);
}
public class ProcessBase
{
public int ID { get; set; }
}
public class InspectorArticle
{
public int ID { get; set; }
public int ProcessBaseID { get; set; }
}
public class InspectorSample
{
public int ID { get; set; }
public int InspectorArticleID { get; set; }
}
Результаты:
Итак, если вы хотите сохранить оператор Linq как есть и выполнить цикл с несколькими операторами foreach, вам нужно использовать что-то вроде приведенного ниже кода:
foreach(var article in results.GroupBy(g => g.obj2.ID))
{
Console.WriteLine("Article ID: #{0}", article.Key);
foreach(var sample in results
.Where(s => s.obj3.InspectorArticleID == article.Key)
.Select(s => s.obj3))
{
Console.WriteLine("\tSample ID: #{0}", sample.ID);
}
}
Использование этого кода (и продолжение примера выше) должно дать вам вывод:
Article ID: #3
Sample ID: #6
Sample ID: #7
Sample ID: #8
Article ID: #4
Sample ID: #9
Недостатком этого подхода является то, что вам приходится перечислять список результатов несколько раз. Если вы знаете, что этот список всегда будет маленьким, то это не такая уж большая проблема. Если список будет очень большим, то вы можете придумать лучший способ вернуть данные.
EDIT
Чтобы сделать код более эффективным, вы можете сгруппировать по InspectorArticle.ID
, а затем создать Dictionary
с ключом ID
, содержащий исходный InspectorArticle
и связанный InspectorSamples
.
var articles = results.GroupBy(g => g.obj2.ID)
.ToDictionary(k => k.Key, v => new {
InspectorArticle = v.Select(s => s.obj2).First(),
InspectorSamples = v.Select(s => s.obj3) });
foreach(var article in articles.OrderBy(a => a.Key).Select(kv => kv.Value))
{
Console.WriteLine("Article ID: #{0}", article.InspectorArticle.ID);
foreach(var sample in article.InspectorSamples)
{
Console.WriteLine("\tSample ID: #{0}", sample.ID);
}
}
Приведенный выше код даст те же результаты, что и мой первый пример, но для более длинных списков статей и примеров будет более эффективным, поскольку он будет перечислять весь список только один раз при построении Dictionary
.
Обратите внимание, что я отключил Dictionary
свойства ID
, потому что я не поставил IEqualityComparer
для метода GroupBy
. Если вы предпочитаете вводить сам объект InspectorArticle
, вам нужно убедиться, что два разных экземпляра InspectorArticle
с одинаковым ID
считаются равными, что можно сделать, если вы создадите IEqualityComparer
и передадите это в методе GroupBy
.