объединить соединение с String.Contains в запросе Linq - PullRequest
4 голосов
/ 01 сентября 2009

У меня есть следующий запрос linq, который создает левое соединение между двумя таблицами:

            var joinResultRows = from leftTable in dataSet.Tables[leftTableName].AsEnumerable()
                             join
                                  rightTable in dataSet.Tables[rightTableName].AsEnumerable()
                                    on leftTable.Field<string>(leftComparedColumnName) equals rightTable.Field<string>(rightComparedColumnName)
                                        into leftJoinedResult
                             select new { leftTable, leftJoinedResult };

я хочу получить строки, которые отвечают на это: строковое значение в левом столбце содержит строковое значение в правом столбце.

Я попробовал это:

            var joinResultRows = from leftTable in dataSet.Tables[leftTableName].AsEnumerable()
                             join
                                  rightTable in dataSet.Tables[rightTableName].AsEnumerable()
                                    on leftTable.Field<string>(leftComparedColumnName).Contains(rightTable.Field<string>(rightComparedColumnName)) equals true
                                        into leftJoinedResult
                             select new { leftTable, leftJoinedResult };

, но это не работает, потому что rightTable не распознается в левой части объединения.

Как мне создать объединение, которое приводит к String.Contains, я делаю содержимое в предложении 'where' или в предложении 'On'?

Ответы [ 2 ]

5 голосов
/ 01 сентября 2009

Вы пробовали SelectMany?

var result =
 from left in dataSet.Tables[leftTableName].AsEnumerable()
 from right in dataSet.Tables[rightTableName].AsEnumerable()
 where left.Field<string>(leftComparedColumnName).Contains(right.Field<string>(rightComparedColumnName))
 select new { left, right };

Редактировать:

Следующее должно иметь желаемый эффект:

class ContainsEqualityComparer: IEqualityComparer<string>
{
    public bool Equals(string right, string left) { return left.Contains(right); }
    public int GetHashCode(string obj) { return 0; }
}

var result =
    dataSet.Tables[leftTableName].AsEnumerable().GroupJoin(
        dataSet.Tables[rightTableName].AsEnumerable(),
        left => left,
        right => right,
        (left, leftJoinedResult) => new { left = left, leftJoinedResult = leftJoinedResult },
        new ContainsEqualityComparer());

Сравнение ключей выполняется через пользовательский IEqualityComparer. Две строки будут объединены только тогда, когда GetHashCode () слева и справа совпадают, и Equals возвращает true.

Надеюсь, это поможет.

3 голосов
/ 09 сентября 2009

Я решил это, создав SelectMany (объединение), в котором левая таблица содержит все записи, а правая содержит ноль, если совпадений нет:

var joinResultRows = from leftDataRow in dataSet.Tables[leftTableName].AsEnumerable()
                             from rightDataRow in dataSet.Tables[rightTableName].AsEnumerable()
                             .Where(rightRow => 
                                 {
                                     // Dont include "" string in the Contains, because "" is always contained
                                     // in any string.                                         
                                     if ( String.IsNullOrEmpty(rightRow.Field<string>(rightComparedColumnName)))
                                         return false;

                                     return leftDataRow.Field<string>(leftComparedColumnName).Contains(rightRow.Field<string>(rightComparedColumnName));

                                 }).DefaultIfEmpty() // Makes the right table nulls row or the match row
                              select new { leftDataRow, rightDataRow };

Спасибо за совет :)

...