[英]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.