LINQ à SQL: jointures multiples sur plusieurs colonnes. Est-ce possible?

donnée:

un tableau nommé TABLE_1 avec les colonnes suivantes:

  • ID
  • ColumnA
  • ColumnB
  • ColumnC

j'ai requête SQL où TABLE_1 se joint sur lui-même deux fois basé hors de ColumnA , ColumnB , ColumnC . La requête peut sembler 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 que cette requête soit réécrite dans LINQ. J'ai essayé de tenter ma chance:

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 dans LINQ? Ce que je fais mal?

106
demandé sur DJTripleThreat 2011-03-15 08:07:16

8 réponses

joindre sur plusieurs colonnes dans Linq à 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 profiter des types anonymes et composer un type pour les colonnes multiples que vous souhaitez comparer.

cela semble confus au début, mais une fois que vous vous familiarisez avec la façon dont le SQL est composé à partir des expressions, il fera beaucoup plus de sens, sous les couvertures cela générera le type de jointure que vous recherchez.

EDIT Ajouter un exemple pour la deuxième jointure basé sur un commentaire.

var query =
    from t1 in myTABLE1List // List<TABLE_1>
    join t2 in myTABLE1List
      on new { A = t1.ColumnA, B = t1.ColumnB } equals new { A = t2.ColumnA, B = t2.ColumnB }
    join t3 in myTABLE1List
      on new { A = t2.ColumnA, B =  t2.ColumnB } equals new { A = t3.ColumnA, B = t3.ColumnB }
    ...
195
répondu Quintin Robinson 2015-07-24 07:01:48

dans LINQ2SQL vous avez rarement besoin de joindre explicitement lorsque vous utilisez des jointures intérieures.

si vous avez de bonnes relations de clé étrangère dans votre base de données, vous obtiendrez automatiquement une relation dans le créateur de LINQ (si non vous pouvez créer une relation manuellement dans le créateur, bien que vous devriez vraiment avoir des relations appropriées dans votre base de données)

parent-child relation

alors vous pouvez juste accéder aux tables lié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,
        };

générera 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 spéciales et pas la mécanique réelle de la jointure.

Modifier

Ceci n'est bien sûr applicable que lorsque vous souhaitez rejoindre la ligne avec notre modèle de base de données. Si vous voulez rejoindre "outside the model" Vous devez recourir manuel rejoint comme dans le réponse à partir de Quintin Robinson

9
répondu Albin Sunnanbo 2017-05-23 12:26:20

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;
        }
9
répondu BionicCyborg 2012-07-13 05:14:03

U peut également 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 }
8
répondu Baqer Naqvi 2014-10-21 14:09:01

je voudrais donner un autre exemple dans lequel plusieurs (3) jointures sont utilisées.

 DataClasses1DataContext ctx = new DataClasses1DataContext();

        var Owners = ctx.OwnerMasters;
        var Category = ctx.CategoryMasters;
        var Status = ctx.StatusMasters;
        var Tasks = ctx.TaskMasters;

        var xyz = from t in Tasks
                  join c in Category
                  on t.TaskCategory equals c.CategoryID
                  join s in Status
                  on t.TaskStatus equals s.StatusID
                  join o in Owners
                  on t.TaskOwner equals o.OwnerID
                  select new
                  {
                      t.TaskID,
                      t.TaskShortDescription,
                      c.CategoryName,
                      s.StatusName,
                      o.OwnerName
                  };
3
répondu user3477428 2017-10-07 03:08:15

vous pouvez également rejoindre si le nombre de colonnes ne sont pas les mêmes dans les deux tableaux et peut mapper la valeur statique à la colonne de tableau

from t1 in Table1 
join t2 in Table2 
on new {X = t1.Column1, Y = 0 } on new {X = t2.Column1, Y = t2.Column2 }
select new {t1, t2}
0
répondu Ankit Arya 2017-11-02 08:00:20

à mon avis, c'est la façon la plus simple de 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
-4
répondu Praveen Kumar 2012-09-21 08:37:09

Vous pouvez écrire votre requête comme ceci.

var query = from t1 in myTABLE1List // List<TABLE_1>
            join t2 in myTABLE1List
               on t1.ColumnA equals t2.ColumnA
               and t1.ColumnB equals t2.ColumnA

Si vous voulez comparer votre colonne avec plusieurs colonnes.

-7
répondu Anvesh 2011-03-15 05:39:47