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?
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 }
...
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)
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
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;
}
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 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
};
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}
à 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
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.