基本上,我想要做的是将两个表外部连接并将它们呈现在一个平坦的结果中。为简单起见,我的两个表看起来像这样:
tot["nameA", "nameB", "nameC"]
critItg["nameA", "nameB"]
我希望左外连接后的结果如下所示:
leftName, rightName
"nameA", "nameA"
"nameB", "nameB"
"nameC", empty/null
我设法通过以下方式执行左外连接:
var res = tot.GroupJoin
(
critITG,
left => left.totName,
right => right.critITGName,
(left, right) => new
{
tot = left,
critITG = right.FirstOrDefault()
}
);
但是,结果分组如下:
{ 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
}
);
感谢您的帮助!
答案 0 :(得分:3)
看起来你已经陷入了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();
答案 1 :(得分:2)
不确定这是否是您需要的......但您是否尝试过选择每个字段的名称?
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和critITGName添加到他的代码中。
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) };
答案 2 :(得分:1)
此处您不需要SelectMany
。您可以使用Select
,但只需在传递给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
};
}
);
答案 3 :(得分:1)
嗨与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()
});