C# Linq DefaultIfEmpty 左连接
C# Linq DefaultIfEmpty LeftJoin
某些代理在组字段中为空。
我正在尝试执行 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})" }));
有什么问题吗?
谢谢大家,我找到了答案
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
来执行左连接样式 link,它使用 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 不启用左连接行为;如果调用它的序列具有零个元素,那么 returns 包含目标类型的一项(并具有该类型的默认值)的序列只是一种便利。本质上就像:
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 个 Agent 组。
我会使用更多的全名,因为不幸的是你要加入一个叫做 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})"
}
);
某些代理在组字段中为空。 我正在尝试执行 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})" }));
有什么问题吗?
谢谢大家,我找到了答案
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
来执行左连接样式 link,它使用 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 不启用左连接行为;如果调用它的序列具有零个元素,那么 returns 包含目标类型的一项(并具有该类型的默认值)的序列只是一种便利。本质上就像:
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 个 Agent 组。
我会使用更多的全名,因为不幸的是你要加入一个叫做 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})"
}
);