149 votes

LINQ to SQL: Plusieurs jointures SUR plusieurs Colonnes. Est-ce possible?

Donnée:

Une table nommée TABLE_1 avec les colonnes suivantes:

  • ID
  • ColumnA
  • ColumnB
  • ColumnC

J'ai une requête SQL où TABLE_1 des jointures sur elle-même deux fois à partir d' ColumnA, ColumnB, ColumnC. La requête devrait ressembler à quelque chose comme ceci:

Select t1.ID, t2.ID, t3.ID
  From TABLE_1 t1
  Left Join TABLE_1 t2 On
       t1.ColumnA = t2.ColumnA
   And t1.ColumnB = t2.ColumnB
   And t1.ColumnC = t2.ColumnC
  Left Join TABLE_1 t3 On
       t2.ColumnA = t3.ColumnA
   And t2.ColumnB = t3.ColumnB
   And t2.ColumnC = t3.ColumnC
... and query continues on etc.

Problème:

J'ai besoin de cette Requête à être réécrit dans LINQ. J'ai essayé de prendre un coup de couteau à elle:

var query =
    from t1 in myTABLE1List // List<TABLE_1>
    join t2 in myTABLE1List
      on t1.ColumnA equals t2.ColumnA
      && t1.ColumnB equals t2.ColumnA
    // ... and at this point intellisense is making it very obvious
    // I am doing something wrong :(

Comment puis-je écrire ma requête LINQ? Ce que je fais mal?

280voto

Quintin Robinson Points 41988

Le rejoindre sur plusieurs colonnes dans Linq to SQL est un peu différent.

var query =
    from t1 in myTABLE1List // List<TABLE_1>
    join t2 in myTABLE1List
      on new { t1.ColumnA, t1.ColumnB } equals new { t2.ColumnA, t2.ColumnB }
    ...

Vous devez prendre avantage de types anonymes et de composer un type pour plusieurs colonnes que vous souhaitez comparer.

Cela semble déroutant au premier abord, mais une fois que vous vous familiariser avec la façon dont le SQL est composé à partir d'expressions, il va faire beaucoup plus de sens, sous les couvertures cela va générer le type de jointure que vous recherchez.

EDIT Ajout d'exemple pour la deuxième jointure basée sur commentaire.

var query =
    from t1 in myTABLE1List // List<TABLE_1>
    join t2 in myTABLE1List
      on new { t1.ColumnA, t1.ColumnB } equals new { t2.ColumnA, t2.ColumnB }
    join t3 in myTABLE1List
      on new { t2.ColumnA, t2.ColumnB } equals new { t3.ColumnA, t3.ColumnB }
    ...

15voto

baqer_naqvi Points 337

U peut aussi utiliser :

var query =
    from t1 in myTABLE1List 
    join t2 in myTABLE1List
      on new { ColA=t1.ColumnA, ColB=t1.ColumnB } equals new { ColA=t2.ColumnA, ColB=t2.ColumnB }
    join t3 in myTABLE1List
      on new {ColC=t2.ColumnA, ColD=t2.ColumnB } equals new { ColC=t3.ColumnA, ColD=t3.ColumnB }

12voto

BionicCyborg Points 51

Title_Authors est un coup d'oeil à deux des choses les rejoindre à un moment les résultats du projet et de continuer le chaînage

        DataClasses1DataContext db = new DataClasses1DataContext();
        var queryresults = from a in db.Authors                                          
                    join ba in db.Title_Authors                           
                    on a.Au_ID equals ba.Au_ID into idAuthor
                    from c in idAuthor
                    join t in db.Titles  
                    on c.ISBN equals t.ISBN 
                    select new { Author = a.Author1,Title= t.Title1 };

        foreach (var item in queryresults)
        {
            MessageBox.Show(item.Author);
            MessageBox.Show(item.Title);
            return;
        }

12voto

Albin Sunnanbo Points 30722

Dans LINQ2SQL vous avez rarement besoin d'adhérer explicitement lors de l'utilisation de jointures internes.

Si vous avez une relation de clé étrangère dans votre base de données, vous obtenez automatiquement un rapport dans le concepteur LINQ (si non, vous pouvez créer un rapport manuellement dans le concepteur, bien que vous devriez vraiment avoir de bonne relations dans votre base de données)

parent-child relation

Ensuite, vous pouvez accéder à des tables associées avec le "point de notation"

var q = from child in context.Childs
        where child.Parent.col2 == 4
        select new
        {
            childCol1 = child.col1,
            parentCol1 = child.Parent.col1,
        };

va générer la requête

SELECT [t0].[col1] AS [childCol1], [t1].[col1] AS [parentCol1]
FROM [dbo].[Child] AS [t0]
INNER JOIN [dbo].[Parent] AS [t1] ON ([t1].[col1] = [t0].[col1]) AND ([t1].[col2] = [t0].[col2])
WHERE [t1].[col2] = @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [4]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

À mon avis, c'est beaucoup plus lisible et vous permet de vous concentrer sur vos conditions particulières et non pas les mécanismes réels de la jointure.

Modifier
Bien sûr, cela est applicable uniquement lorsque vous souhaitez vous joindre à la ligne avec notre modèle de base de données. Si vous voulez vous joindre "en dehors du modèle" vous devez recourir à manuel rejoint comme dans la réponse de Quintin Robinson

-4voto

Praveen Kumar Points 1

À mon avis, c'est le moyen le plus simple pour joindre deux tables avec plusieurs champs:

from a in Table1 join b in Table2    
       on (a.Field1.ToString() + "&" + a.Field2.ToString())     
       equals  (b.Field1.ToString() + "&" + b.Field2.ToString())  
     select a

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X