C# Linq DefaultIfEmpty LeftJoin
Posted
技术标签:
【中文标题】C# Linq DefaultIfEmpty LeftJoin【英文标题】: 【发布时间】:2022-01-07 21:44:39 【问题描述】:某些代理在组字段中为空。 我正在尝试进行 LeftJoin,但收到类似 InnerJoin 的结果(仅限具有非空组的代理)
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://***.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)" ));
【问题讨论】:
你是说组是空的吗? Agents 中会有 100 条唯一记录,Groups 中只有 80 条唯一记录? (所以 20 个代理没有组) 【参考方案1】:方法语法不使用Join
来执行左连接样式链接,它使用GroupJoin
。如果你直接Join
,那么右边(Group)缺少一个元素将意味着左边(Agent)的元素消失。
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
将保留左边的元素,如果没有匹配则使右边的元素为空序列
如果您需要将其作为具有重复元素的列表退出,您可以选择 SelectMany 它,它会扩展 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 个元素的集合进行操作。因为 Joe 没有地址,所以 SelectMany 会跳过他,他会从输出中丢失
总而言之,这意味着您应该执行GroupJoin
,并且您在任何地方都不需要DefaultIfEmpty
,因为您没有执行SelectMany
/您可以容忍其中有0个代理组其他方式。
我会使用更多的全名,因为不幸的是你加入了一个名为 Group 的类(我猜),并且 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)"
);
【讨论】:
以上是关于C# Linq DefaultIfEmpty LeftJoin的主要内容,如果未能解决你的问题,请参考以下文章