2009-09-01 5 views
4

я следующий запрос LINQ, что создать левое соединение между двумя таблицами:Комбинат присоединиться String.Contains в 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

Я решил ее создания 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 }; 

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

5

Вы пробовали 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 }; 

Edit:

Ниже следует иметь желаемый эффект:

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.

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

+0

+1 для SelectMany - LINQ поддерживает только «equi-joins», которые объединяют элементы в последовательности с помощью равенства ключей. – dahlbyk

+0

selectMany - это то, о чем я не думал, спасибо. он находит совпадения, но не решает мою проблему, , потому что мне нужна LEFT JOIN, которая создает новую объединенную таблицу или по крайней мере анонимный тип, который имеет две таблицы - левую и объединенную (например, в моем примере выше). после выполнения моего запроса выше, я построил таблицу результатов вручную, используя leftTable, leftJoinedResult. Могу ли я сделать SelectMany слева? – Rodniko

+0

Я считаю, что нет реального способа добиться того, что вы пытаетесь использовать с LinQ и анонимными типами. Однако существует ряд обходных путей, и я постараюсь выработать для вас в вышеупомянутом сообщении. –