繁体   English   中英

C# Linq DefaultIfEmpty LeftJoin

[英]C# Linq DefaultIfEmpty LeftJoin

一些代理在组字段中有 null。 我正在尝试进行 LeftJoin,但收到类似 InnerJoin 的结果(仅限没有 null 组的代理)

Agents = new ObservableCollection<dynamic>((await _repository.GetAgentsAsync() ?? new Agent[] { })
            .Join(Groups.DefaultIfEmpty(), a => a.Group, g => g.ID, (a, g) =>
            new { ID = a.ID, AgentName = a.AgentName, Login = a.Login, AgentID = a.AgentID, IsDel = a.IsDel, Group = g == null ? "Empty" : $"{g.NameGroup} ({g.Num})" }));

问题是什么?

谢谢大家,我找到了答案https://stackoverflow.com/a/21584913/13618303

        Groups = new ObservableCollection<Group>(await _repository.GetGroupsAsync() ?? new Group[] { });
        Agents = new ObservableCollection<Agent>(await _repository.GetAgentsAsync() ?? new Agent[] { });
        AgentsGroups = new ObservableCollection<dynamic>(Agents.GroupJoin(Groups, a => a.Group, g => g.ID, (a, g) => new { Agent = a, Group = g})
            .SelectMany(ag => ag.Group.DefaultIfEmpty(), (a,g) => new { Agent = a.Agent, Group = g })
            .Select ( ag => new { ID = ag.Agent.ID, AgentName = ag.Agent.AgentName, Login = ag.Agent.Login, AgentID = ag.Agent.AgentID, IsDel = ag.Agent.IsDel, Group = ag.Group == null ? "Empty" : $"{ag.Group.NameGroup} ({ag.Group.Num})" }));

方法语法不使用Join来执行左连接样式链接,它使用GroupJoin 如果你直接Join ,那么右边(组)缺少一个元素将意味着左边的元素(代理)消失。

GroupJoin 将左侧的元素与右侧的多个匹配元素配对

Left
1, John
2, Mary
3, Joe

Right
1, The Street, 1996
1, The Avenue, 2002
2, The Road, 2010

约翰住在两个地方,玛丽住在一个地方。 乔从来没有住过任何地方。 Left.GroupJoin(Right)产生:

{1, John}, [ {1, The Street, 1996}, {1, The Avenue, 2002} ]
{2, Mary}, [ {1, The Road, 2010} ]
{3, Joe},  [ ]

GroupJoin将保留左边的元素,如果没有匹配则使右边的元素为空序列

如果您需要将其作为具有重复元素的列表退出,您可以选择它,它会扩展 person:addresses 表示的列表列表。 我会回到这个。


DefaultIfEmpty 不启用左连接行为; 如果调用它的序列具有零个元素,则返回包含目标类型的一项(并具有该类型的默认值)的序列只是一种便利。 本质上它就像:

public int[] DefaultIfEmpty(int[] input){
  if(input.Length == 0)
    return new int[1]; //a single integer, value 0 --> the default for int
  else
    return input;
}

您不需要在群组中使用它; 无论如何,这将是一个非操作,因为如果有 0 个组,将其转换为单个null组的列表将表现相同(没有代理会匹配)

如果您计划在分组上使用 SelectMany,您确实需要DefaultIfEmpty ,因为 SelectMany 根本不会对 0 个元素的集合进行操作。 因为乔没有地址,SelectMany 会跳过他,他会从 output 中丢失


总而言之,这意味着您应该执行GroupJoin ,并且您在任何地方都不需要DefaultIfEmpty ,因为您没有执行SelectMany /您可以以其他方式容忍代理存在 0 个组。

我将使用更多全名,因为不幸的是您加入了一个名为 Group 的 class(我猜),并且 groupjoin 为您提供了一个代理列表,并且列表中的每个代理都有一个匹配组的列表:

.GroupJoin(Groups, agent => agent.Group, group => group.ID, (agent, groupCollection) =>
    new {  
        agent.ID, 
        agent.AgentName,
        agent.Login,
        agent.AgentID, 
        agent.IsDel, 
        GroupNameAndNum = groupCollection.Select(g => $"{g.NameGroup} ({g.Num})").FirstOrDefault() ?? "Empty" 
    }
);

如果您使用的是SelectMany(也许您有具有 2 个组的代理并希望将它们分别列出,并重复代理数据),它可能看起来像:

.GroupJoin(Groups, agent => agent.Group, group => group.ID, (agent, groupCollection) => new { Agent = agent, OneOrMoreGroups = groupCollection.DefaultIfEmpty() })
.SelectMany(
    agentWithGroupsCollection => agentWithGroupsCollection.OneOrMoreGroups,
    (agentWithGroupsCollection, groupsCollectionItem) =>

    new {  
        agentWithGroupsCollection.ID, 
        agentWithGroupsCollection.AgentName,
        agentWithGroupsCollection.Login,
        agentWithGroupsCollection.AgentID, 
        agentWithGroupsCollection.IsDel, 
        GroupNameAndNum = groupsCollectionItem == null ? "Empty" : $"{groupsCollectionItem.NameGroup} ({groupsCollectionItem.Num})"
    }
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM