既然你要加入的记录在一起,这种说法是不正确的:
现在这个结果集都只有一个ProcessBases,每个ProcessBase 将有多个InspectorArticles每个InspectorArticle将 有多个InspectorSamples。
你将真正拥有你执行查询后是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语句遍历它,你需要使用类似代码belo女:
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
这种方法的缺点是,你不必列举结果列表中的几个倍。如果你知道这个清单总是很小,那么这不是什么大不了的事。如果列表非常大,那么您可能想要提供更好的方式来返回数据。
编辑
为了使代码更有效,你可以按InspectorArticle.ID
,然后创建由ID
键控Dictionary
,并包含原始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
对象本身,则需要确保将具有相同ID
的两个不同InspectorArticle
实例视为相同,如果您创建IEqualityComparer
并将其传递给GroupBy
方法,则可以完成此操作。
非常感谢你:) – 2012-03-17 07:25:32
很高兴我能帮忙! – rsbarro 2012-03-17 11:37:44
@ClunkyCoder再想一想,如果你有更长的列表,发布一个更有效的方法。 – rsbarro 2012-03-17 15:56:35