2013-09-11 4 views
4

Я пытаюсь сделать запрос left outer join, который также имеет custom comparator.Linq left external join with custom compator

У меня есть следующие списки:

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.

Мне все равно, есть ли результат в синтаксисе запроса или методах расширения.

+0

Вы можете переопределить Equals ColumnInformations и GetHashCode, как реализовано в ColumnComparer. –

+0

@HamletHakobyan, я переопределил 'Equals' в' ColumnInformation'. Сейчас мой код не трогает его. Какая польза от этого (также для GetHashCode)? – gunr2171

+0

Должен сказать, что ** вы можете делать все, что хотите в LINQ ** с помощью методов расширения, но ** вы не можете делать некоторые вещи в LINQ с синтаксисом запроса **. Фактически эквивалент 'join into' в' методах расширения' - 'GroupJoin'. –

ответ

3

, как вы делаете это с 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 } 
    ); 
+0

OP сказал: «Мой вопрос: как я могу сделать как левое внешнее соединение, так и использовать мой компаратор одновременно?». Интересно, как этот ответ является ответом на настоящую потребность в OP !? – Alireza

+1

@Alireza, это делает левое внешнее соединение (используя 'DefaultIfEmpty()') и использует мой компаратор ('cc'). Это правильный ответ. – gunr2171

+0

@ gunr2171 Упс! Извините, я не заметил ** 'cc' **. Спасибо за разъяснение. – Alireza

0

Вы можете воспользоваться подзапрос в сочетании с Где:

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

В конце предложение 'where' будет' l2 == l1'. У меня есть логика сравнения в этом методе оператора. – gunr2171

+0

@ gunr2171 Вы спросили, как связать свой настроенный компаратор с формой запроса Join, правильно? Вы можете вызвать любой метод, возвращающий bool для подачи предложения «Where». Разве это вас не удовлетворяет? – Alireza

+0

Не поймите меня неправильно, ваш ответ был в порядке, и я только немного уточнил, но это было не так. Мне просто пришлось пойти с другим ответом, потому что это имело смысл для меня. – gunr2171