Linq 左外部连接与自定义比较器

本文关键字:自定义 比较器 连接 外部 Linq | 更新日期: 2023-09-27 18:30:54

我正在尝试进行一个left outer join查询,该查询也具有custom comparator

我有以下列表:

List<ColumnInformation> list1;
List<ColumnInformation> list2;

它们保存有关 SQL 列的信息(数据类型、名称、表等)。我已经覆盖了班级的Equals,并做了一个operator ==operator !=

我了解如何进行左外连接:

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关键字的任何内容。

我不在乎结果是在查询语法还是扩展方法中。

Linq 左外部连接与自定义比较器

执行此操作的方法是使用GroupJoinSelectMany(以平展结果):

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 } 
    );

您可以将子查询与 其中

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
};