Donné:
Une table nommée TABLE_1
avec les colonnes suivantes:
ID
ColumnA
ColumnB
ColumnC
J'ai une requête SQL où TABLE_1
rejoint sur lui-même deux fois basé sur ColumnA
, ColumnB
, ColumnC
. La requête pourrait ressembler à 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 écrire ma requête dans LINQ? Qu'est-ce que je fais mal?
La jonction sur plusieurs colonnes dans Linq to SQL est un peu différente.
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 tirer parti des types anonymes et composer un type pour les multiples colonnes avec lesquelles vous souhaitez comparer.
Cela semble déroutant au début, mais une fois que vous aurez compris la façon dont le code SQL est composé à partir des expressions, cela aura plus de sens, sous les couvertures, cela générera le type de jointure que vous recherchez.
EDITAjout d'un exemple pour la deuxième jointure basée 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 }
...
Title_Authors est une recherche de deux choses joignent à la fois les résultats du projet et continuent à chaîner
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;
}
Dans LINQ2SQL, vous devez rarement explicitement vous joindre lorsque vous utilisez des jointures internes.
Si vous avez des relations de clé étrangère appropriées dans votre base de données, vous obtiendrez automatiquement une relation dans le concepteur LINQ (sinon, vous pouvez créer une relation manuellement dans le concepteur, même si vous devez vraiment avoir des relations appropriées dans votre base de données).
Ensuite, vous pouvez simplement accéder aux tables associées avec la "notation par points"
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, cela est beaucoup plus lisible et vous permet de vous concentrer sur vos conditions spéciales et non sur les mécanismes réels de la jointure.
Modifier
Ceci n’est bien sûr applicable que lorsque vous souhaitez rejoindre le modèle de base de données. Si vous souhaitez rejoindre "en dehors du modèle", vous devez recourir aux jointures manuelles, comme indiqué dans le answer from Quintin Robinson
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 }
Je voudrais donner un autre exemple dans lequel des jointures multiples (3) 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
};
Vous pouvez également participer si le nombre de colonnes n'est pas identique dans les deux tables et mapper une valeur statique sur une colonne de table.
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}