带有自定义比较器的 Linq 左外连接
Posted
技术标签:
【中文标题】带有自定义比较器的 Linq 左外连接【英文标题】:Linq left outer join with custom comparator 【发布时间】:2013-09-15 18:27:46 【问题描述】:我正在尝试创建一个left outer join
查询,该查询也有一个custom comparator
。
我有以下列表:
List<ColumnInformation> list1;
List<ColumnInformation> list2;
这些包含有关 SQL 列的信息(数据类型、名称、表等)。我已经为班级覆盖了Equals
,并创建了operator ==
和operator !=
。
我知道怎么make a left outer join:
var leftOuterJoin = from l1 in list1
join l2 in list2 on l1.objectID equals l2.objectID into temp
from l2 in temp.DefaultIfEmpty(new l1.ID, Name = default(string) )
select new
l1.ID,
ColumnName1 = l1.Name,
ColumnName2 = l2.Name,
;
而且我了解如何制作和使用自定义IEqualityComparer
:
public class ColumnComparer : IEqualityComparer<ColumnInformation>
public bool Equals(ColumnInformation x, ColumnInformation y)
return x == y; //this uses my defined == operator
public int GetHashCode(ColumnInformation obj)
return 1; //forcing the join to use Equals, just trust me on this
ColumnComparer cc = new ColumnComparer();
var joinedList = list1.Join(list2,
x => x,
y => y,
(x, y) => new x, y,
cc);
我的问题是:如何同时进行左外连接和使用比较器?
据我所知,查询语法没有比较器的关键字,扩展方法没有into
关键字的任何东西。
我不在乎结果是查询语法还是扩展方法。
【问题讨论】:
您可以覆盖ColumnInformations
Equals 和 GetHashCode,如在 ColumnComparer 中实现的那样。
@HamletHakobyan,我已经覆盖了ColumnInformation
中的Equals
。现在我的代码没有触及它。这有什么好处(也适用于 GetHashCode)?
我不得不说你可以用扩展方法在LINQ中做所有你想做的事情但是你不能用查询语法在LINQ中做一些事情。事实上,extension methods
中的join into
等价于GroupJoin
。
@KingKing, GroupJoin
,不会从名字中猜到这一点。如果你能提供一个例子,我会很高兴。
很抱歉造成混淆。尝试在ColumnInformation
中实现IEquatable<T>。
【参考方案1】:
您这样做的方式是使用GroupJoin
和SelectMany
(以使结果变平):
ColumnComparer cc = new ColumnComparer();
var joinedList = list1
.GroupJoin(list2,
x => x,
y => y,
(x, g) => new x, g,
cc)
.SelectMany(
z => z.g.DefaultIfEmpty(),
(z, b) => new x = z.x, y = b
);
【讨论】:
OP 说“我的问题是:如何同时进行左外连接和使用比较器?”。我想知道这个答案如何响应 OP 的实际需求!? @Alireza,这是一个左外连接(使用DefaultIfEmpty()
),并使用我的比较器(cc
)。这是一个正确的答案。
@gunr2171 哎呀!抱歉,我没有注意到 'cc'。感谢您的澄清。【参考方案2】:
您可以将子查询与 Where 结合使用:
var leftOuterJoin = from l1 in list1
select new
jointList = (from l2 in list2
where l2.objectID == l1.ObjectID // <-- and you can do any other comparing logic in where clause
select l2).DefaultIfEmpty(),
l1id = l1.ID,
ColumnName1 = l1.Name,
ColumnName2 = l2.Name
;
【讨论】:
最后,where
子句将是l2 == l1
。我在那个运算符方法中有我的比较逻辑。
@gunr2171 您询问了如何让您的自定义比较器参与到一个 Join 查询中,对吧?您可以调用任何返回布尔值的方法来提供“Where”子句。这不让你满意吗?
别误会,你的回答很好,我只是补充一点说明,但并没有错。我只是碰巧选择了另一个答案,因为这对我来说很有意义。
@gunr2171 好的。感谢您对已接受的答案进行澄清。我没有完全明白。现在我知道了:D以上是关于带有自定义比较器的 Linq 左外连接的主要内容,如果未能解决你的问题,请参考以下文章