Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq left outer join with custom comparator

Tags:

c#

join

linq

I am trying to make a left outer join query that also has a custom comparator.

I have the following lists:

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

These hold information about an SQL column (datatype, name, table, etc). I have overrided Equals for the class, and made a operator == and operator !=.

I understand how to 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,
                    };

And I understand how to make and use a custom 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);

My question is: How can I do both a left outer join and use my comparator at the same time?

As far as I know, the query syntax does not have a keyword for a comparator, and the extension method does not have anything for the into keyword.

I do not care if the result is in query syntax or extension methods.

like image 952
gunr2171 Avatar asked Sep 11 '13 16:09

gunr2171


1 Answers

The way you do that is with a GroupJoin and SelectMany (to flatten the results):

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 } 
    );
like image 164
D Stanley Avatar answered Sep 23 '22 14:09

D Stanley