C# 在GroupJoin()之后选择many()
基本上,我想做的是将两个表连接起来,并以一个简单的结果显示它们。为简单起见,我的两个表如下所示:C# 在GroupJoin()之后选择many(),c#,linq,C#,Linq,基本上,我想做的是将两个表连接起来,并以一个简单的结果显示它们。为简单起见,我的两个表如下所示: tot["nameA", "nameB", "nameC"] critItg["nameA", "nameB"] leftName, rightName "nameA", "nameA" "nameB", "nameB" "nameC", empty/null { tot = { totName = "nameA" }, { critITG = "nameA"} } { tot = { totN
tot["nameA", "nameB", "nameC"]
critItg["nameA", "nameB"]
leftName, rightName
"nameA", "nameA"
"nameB", "nameB"
"nameC", empty/null
{ tot = { totName = "nameA" }, { critITG = "nameA"} }
{ tot = { totName = "nameB" }, { critITG = "nameB"} }
{ tot = { totName = "nameC" }, { critITG = null} }
{ totName = "nameA", critITG = "nameA" }
我希望左外部联接后的结果如下所示:
tot["nameA", "nameB", "nameC"]
critItg["nameA", "nameB"]
leftName, rightName
"nameA", "nameA"
"nameB", "nameB"
"nameC", empty/null
{ tot = { totName = "nameA" }, { critITG = "nameA"} }
{ tot = { totName = "nameB" }, { critITG = "nameB"} }
{ tot = { totName = "nameC" }, { critITG = null} }
{ totName = "nameA", critITG = "nameA" }
我已通过以下方式成功执行左外连接:
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => new
{
tot = left,
critITG = right.FirstOrDefault()
}
);
但是,结果按如下方式分组:
tot["nameA", "nameB", "nameC"]
critItg["nameA", "nameB"]
leftName, rightName
"nameA", "nameA"
"nameB", "nameB"
"nameC", empty/null
{ tot = { totName = "nameA" }, { critITG = "nameA"} }
{ tot = { totName = "nameB" }, { critITG = "nameB"} }
{ tot = { totName = "nameC" }, { critITG = null} }
{ totName = "nameA", critITG = "nameA" }
我希望结果看起来更像这样:
tot["nameA", "nameB", "nameC"]
critItg["nameA", "nameB"]
leftName, rightName
"nameA", "nameA"
"nameB", "nameB"
"nameC", empty/null
{ tot = { totName = "nameA" }, { critITG = "nameA"} }
{ tot = { totName = "nameB" }, { critITG = "nameB"} }
{ tot = { totName = "nameC" }, { critITG = null} }
{ totName = "nameA", critITG = "nameA" }
我已经读到,展平左侧外部联接结果的解决方案是SelectMany(),但在上面的结果集中实现它时遇到了困难。以下结果集为“对象引用未设置为对象的实例”:
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => new
{
tot = left,
critITG = right.FirstOrDefault()
}
)
.SelectMany
(
right => right.critITG.critITGName.DefaultIfEmpty(),
(left, right) =>
new
{
leftName = left.tot.totName,
rightName = right
}
);
感谢您的帮助!您不需要在此处选择多个。您可以使用
选择
,但您只需在传递给GroupJoin的代理中选择所需的数据即可:
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => {
var mr = right.FirstOrDefault();
return new
{
totName = left.totName,
critITG = mr == null ? null : mr.critITGName
};
}
);
您不需要在此处选择多个
。您可以使用选择,但您可以在传递给GroupJoin
的委托中选择所需的数据:
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => {
var mr = right.FirstOrDefault();
return new
{
totName = left.totName,
critITG = mr == null ? null : mr.critITGName
};
}
);
看起来你已经陷入了lambda结构的技术细节中,这可能会导致代码的可维护性随着时间的推移而降低。我经常发现查询语法比LAMBDA语法更简单,更易于维护。
var tots = new string[] {"nameA", "nameB", "nameC"};
var critItgs = new string[] {"nameA", "nameB"};
var query = from tot in tots
join critItg in critItgs on tot equals critItg into joined
from row in joined.DefaultIfEmpty()
select new {totName = tot, critItg = row};
query.Dump();
看起来你已经陷入了lambda结构的技术细节中,这可能会导致代码的可维护性随着时间的推移而降低。我经常发现查询语法比LAMBDA语法更简单,更易于维护。
var tots = new string[] {"nameA", "nameB", "nameC"};
var critItgs = new string[] {"nameA", "nameB"};
var query = from tot in tots
join critItg in critItgs on tot equals critItg into joined
from row in joined.DefaultIfEmpty()
select new {totName = tot, critItg = row};
query.Dump();
不确定这是否是您需要的…但您是否尝试过为每个字段选择名称
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => new
{
tot = left.totName,
critITG = right.FirstOrDefault() == null ? null : right.critITGName
}
);
编辑:
我也同意@Jim Wooley,有时候不使用lambda表达式更容易。
请注意,您需要将您的totName和CrititName添加到他的代码中
var res = from totElement in tot
join critItgItem in critItgon totElement.Name equals critItgItem.Name into joined
from row in joined.DefaultIfEmpty()
select new {totName = tot.Name, critItg = (row == null ? String.Empty : row.Name) };
不确定这是否是您需要的…但您是否尝试过为每个字段选择名称
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => new
{
tot = left.totName,
critITG = right.FirstOrDefault() == null ? null : right.critITGName
}
);
编辑:
我也同意@Jim Wooley,有时候不使用lambda表达式更容易。
请注意,您需要将您的totName和CrititName添加到他的代码中
var res = from totElement in tot
join critItgItem in critItgon totElement.Name equals critItgItem.Name into joined
from row in joined.DefaultIfEmpty()
select new {totName = tot.Name, critItg = (row == null ? String.Empty : row.Name) };
Hi与Lee的示例类似,但有些不同,这里我在要返回的最终匿名类型中使用了select语句:
var res = tot.GroupJoin(critItg,
left => left.Name,
right => right.Name,
(left, right) => new
{
tot = left.Name,
critItg = right.Select(x => x.Name).FirstOrDefault()
});
Hi与Lee的示例类似,但有些不同,这里我在要返回的最终匿名类型中使用了select语句:
var res = tot.GroupJoin(critItg,
left => left.Name,
right => right.Name,
(left, right) => new
{
tot = left.Name,
critItg = right.Select(x => x.Name).FirstOrDefault()
});
谢谢。但是您的代码给了我一个错误:“mr:mr.critITGName“='无法确定条件表达式的类型,因为'AnonymousType#1'和'string'之间没有隐式转换任何想法?@Skalis-抱歉,如果右侧为null,则应为null,而不是
mr
。我已经更新了代码。@JimWooley-left
和right
不是字符串,否则left=>left.totName
和right=>right.critITGName
不会编译。@Lee,谢谢你的更正。我看到的是最初提议的集合,而不是最初的GroupJoin实现。谢谢。我想这样做,谢谢。但是,您的代码给了我一个错误:“mr:mr.critITGName”=”无法确定条件表达式的类型,因为在“匿名类型#1”和“字符串”之间没有隐式转换。有什么想法吗?@Skalis-对不起,如果右侧为null,则应该为null,而不是mr
。我已经更新了代码。@JimWooley-left
和right
不是字符串,否则left=>left.totName
和right=>right.critITGName
不会编译。@Lee,谢谢你的更正。我看到的是最初提议的集合,而不是最初的GroupJoin实现。谢谢。我想要的工作方式。