当子条件不匹配时,不包括父实体

时间:2016-07-19 14:42:08

标签: sql linq entity-framework-6

我有一个查询,我必须让他们的孩子返回一些实体。

目前,如果没有孩子,父母也不会被退回。我想要的是拥有所有父母的列表,如果有任何孩子,请将其包括在内。

我的Linq查询目前如下:

var query = (from parent in Context.Parents
            join child in Context.Children on child.ParentId.DefaultIfEmpty() equals parent.Id
            where child.SomeProperty == SomeValue
            select new {parent, child});

var result = query.ToList().Select(e => e.parent).Distinct().ToList();

生成以下SQL查询

SELECT 
    [Extent1].[ParentId] AS [ParentId], 
    [Join1].[ChildId] AS [ChildId], 
    [Join1].[SomeProperty] AS [SomeProperty], 
    FROM  [dbo].[Parent] AS [Extent1]
    INNER JOIN  (SELECT [Extent2].[ChildId] AS [ChildId], 
                        [Extent2].[SomeProperty] AS [SomeProperty]
        FROM   ( SELECT 1 AS X ) AS [SingleRowTable1]
        LEFT OUTER JOIN [dbo].[Child] AS [Extent2] ON 1 = 1 ) AS [Join1] ON [Extent1].[ParentId] = [Join1].[ParentId]
    WHERE [Join1].[SomeProperty] = @p__linq__0

我已设法创建我的SQL查询,返回我想要的结果,但我仍然无法在Linq中翻译它

SELECT Distinct Parent.ParentID, fullData.ChildID 
    FROM Parent left outer join 
    (select Child.ParentId, Child.SomeProperty, Child.EmployeurSubsideID 
        from Child 
        Where Child.SomeProperty = 'SomeValue'  ) as fullData on Parent.ParentID = fullData.ParentID

2 个答案:

答案 0 :(得分:2)

这是一个带有额外右侧滤镜的经典LEFT OUTER JOIN

您有两种选择(均可使用):

(A)在加入

之前应用右侧过滤器
var query = 
    from parent in Context.Parents
    join child in Context.Children
        .Where(child => child.SomeProperty == SomeValue)
    on parent.Id equals child.ParentId into children
    from child in children.DefaultIfEmpty()
    select new { parent, child };

(B)使用复合键进行加入:

var query = 
    from parent in Context.Parents
    join child in Context.Children on new { K1 = parent.Id, K2 = SomeValue }
    equals new { K1 = child.ParentId, K2 = child.SomeProperty } into children
    from child in children.DefaultIfEmpty()
    select new { parent, child };

实际上在 LINQ to Entities 中你有第三个选择:

(C)使用where而不是join(查询转换程序识别该模式,生成的SQL查询仍将使用LEFT OUTER JOIN):

var query = 
    from parent in Context.Parents
    from child in Context.Children
        .Where(child => parent.Id == child.ParentId && child.SomeProperty == SomeValue)
        .DefaultIfEmpty()
    select new { parent, child };

答案 1 :(得分:1)

像这样的东西

var query = (from parent in Context.Parents
            join child in Context.Children on child.ParentId equals parent.Id
            into ch from c in ch.DefaultIfEmpty()
            where c == null || c.SomeProperty == SomeValue
            select new {parent, c});

或者

(from parent in Context.Parents
where parent.Children == null || parent.Children.Any(c=>c.SomeProperty == SomeValue)
select parent).Include("Children")

假设外键设置正确,并注意子项的属性名称可能不同。