我认为父母和孩子并不是真正适合分开的实体。一个孩子总是可以成为一个父母,通常一个孩子有两个父母(父亲和母亲),所以这不是最简单的情境。但我假设你只有一个简单的1:n关系,就像我使用的以下主从模型。
你需要做的是进行
left outer join(那个答案引导了我走上了正确的道路)。这样的连接有点棘手,但以下是代码。
var query = from m in ctx.Masters
join s in ctx.Slaves
on m.MasterId equals s.MasterId into masterSlaves
from ms in masterSlaves.Where(x => x.Age > 5).DefaultIfEmpty()
select new {
Master = m,
Slave = ms
};
foreach (var item in query) {
if (item.Slave == null) Console.WriteLine("{0} owns nobody.", item.Master.Name);
else Console.WriteLine("{0} owns {1} at age {2}.", item.Master.Name, item.Slave.Name, item.Slave.Age);
}
这将转换为使用 EF 4.1 的以下 SQL 语句。
SELECT
[Extent1].[MasterId] AS [MasterId],
[Extent1].[Name] AS [Name],
[Extent2].[SlaveId] AS [SlaveId],
[Extent2].[MasterId] AS [MasterId1],
[Extent2].[Name] AS [Name1],
[Extent2].[Age] AS [Age]
FROM [dbo].[Master] AS [Extent1]
LEFT OUTER JOIN [dbo].[Slave] AS [Extent2]
ON ([Extent1].[MasterId] = [Extent2].[MasterId]) AND ([Extent2].[Age] > 5)
请注意,在连接的集合上执行附加的年龄where子句而不是在from和select之间执行。
编辑:
如果您想要分层结果,可以通过执行分组来转换平面列表:
var hierarchical = from line in query
group line by line.Master into grouped
select new { Master = grouped.Key, Slaves = grouped.Select(x => x.Slave).Where(x => x != null) };
foreach (var elem in hierarchical) {
Master master = elem.Master;
Console.WriteLine("{0}:", master.Name);
foreach (var s in elem.Slaves)
Console.WriteLine("{0} at {1}", s.Name, s.Age);
}
请注意,我使用了匿名类型来存储分层结果。当然,您也可以创建一个特定的类型,如下所示。
class FilteredResult {
public Master Master { get; set; }
public IEnumerable<Slave> Slaves { get; set; }
}
然后将该组投影到此类的实例中。如果您需要将这些结果传递给其他方法,这样做会更容易。