LINQ to SQL: несколько объединений в нескольких столбцах. Это возможно?
Дано:
Таблица с именем TABLE_1
со следующими столбцами:
-
ID
-
ColumnA
-
ColumnB
-
ColumnC
У меня есть SQL-запрос, где TABLE_1
соединяется сам по себе в два раза с ColumnA
, ColumnB
, ColumnC
. Запрос может выглядеть примерно так:
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.
Проблема:
Мне нужно, чтобы запрос был переписан в LINQ. Я пробовал нанести ему удар:
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 :(
Как написать мой запрос в LINQ? Что я делаю неправильно?
Ответы
Ответ 1
Присоединение к нескольким столбцам в Linq to SQL немного отличается.
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 }
...
Вам нужно использовать анонимные типы и составить тип для нескольких столбцов, которые вы хотите сравнить.
Это кажется запутанным сначала, но как только вы познакомитесь с тем, как SQL составлен из выражений, это будет иметь больший смысл, под обложками это создаст тип соединения, которое вы ищете.
EDIT Добавление примера для второго соединения на основе комментария.
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 }
...
Ответ 2
В LINQ2SQL вам редко нужно явно присоединяться при использовании внутренних соединений.
Если у вас есть правильные отношения с внешними ключами в вашей базе данных, вы автоматически получите отношение в дизайнере LINQ (если вы не можете создать отношение вручную в дизайнере, хотя вы действительно должны иметь правильные отношения в своей базе данных)
![parent-child relation]()
Затем вы можете просто получить доступ к связанным таблицам с помощью "точечной нотации"
var q = from child in context.Childs
where child.Parent.col2 == 4
select new
{
childCol1 = child.col1,
parentCol1 = child.Parent.col1,
};
будет генерировать запрос
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
По-моему, это гораздо более читаемо и позволяет сосредоточиться на ваших особых условиях, а не на действительной механике соединения.
Edit
Это, конечно, применимо только тогда, когда вы хотите присоединиться к линии с нашей моделью базы данных. Если вы хотите присоединиться к "вне модели", вам нужно прибегнуть к ручным объединениям, как в answer от Quintin Robinson
Ответ 3
Title_Authors - это поиск двух вещей, присоединяющихся к результатам проекта времени и продолжения цепочек
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;
}
Ответ 4
U также может использовать:
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 }
Ответ 5
Я хотел бы привести еще один пример, в котором используются множественные (3) соединения.
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
};
Ответ 6
Вы также можете присоединиться, если количество столбцов не одинаково в обеих таблицах и может отображать статическое значение в столбец таблицы
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}
Ответ 7
По-моему, это самый простой способ объединения двух таблиц с несколькими полями:
from a in Table1 join b in Table2
on (a.Field1.ToString() + "&" + a.Field2.ToString())
equals (b.Field1.ToString() + "&" + b.Field2.ToString())
select a
Ответ 8
Вы можете написать свой запрос следующим образом.
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
Если вы хотите сравнить столбец с несколькими столбцами.