2009-09-01 8 views
4

j'ai la requête LINQ suivante qui créent une jointure gauche entre deux tables:moissonneuse-batteuse se joignent à String.Contains dans LINQ requête

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

je veux obtenir les lignes qui répondent ceci: la valeur de chaîne dans la colonne de gauche contient la valeur de chaîne dans la colonne de droite.

i essayé ceci:

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

mais il ne fonctionne pas la cause RightTable n'est pas reconnu dans la partie gauche de la jointure.

Comment puis-je créer une jointure résultant de String.Contains, puis-je faire le contenu de la clause 'where' ou de la clause 'On'?

Répondre

2

Je l'ai résolu en créant SelectMany (joindre) que la table de gauche détient tous les enregistrements et le droit détient null s'il n'y a pas de correspondance:

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

Merci pour l'astuce :)

5

Avez-vous essayé un 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:

Les éléments suivants doivent avoir l'effet désiré:

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

La comparaison clé est exécutée par le IEqualityComparer personnalisé. Deux lignes ne seront jointes que si GetHashCode() de gauche et de droite sont identiques et Equals renvoie true.

Espérons que ça aide.

+0

+1 pour SelectMany - LINQ ne supporte que les "équi-jointures" qui associent des éléments dans les séquences par égalité de clé. – dahlbyk

+0

selectMany est quelque chose que je n'ai pas pensé, merci. il trouve les correspondances mais ne résout pas mon problème, parce que j'ai besoin d'un LEFT JOIN qui crée une nouvelle table jointe ou au moins un type anonyme qui a deux tables - la gauche et la join (comme dans mon exemple ci-dessus). Après avoir exécuté ma requête ci-dessus, j'ai construit la table de résultats manuellement en utilisant leftTable, leftJoinedResult. puis-je faire SelectMany gauche rejoindre? – Rodniko

+0

Je crois qu'il n'y a aucun moyen réel de réaliser ce que vous essayez avec LinQ et les types anonymes. Cependant, il existe un certain nombre de solutions de contournement, je vais essayer de travailler pour vous dans le post ci-dessus. –