LINQ к SQL: несколько соединений на нескольких столбцах. Это возможно?
-
24-10-2019 - |
Вопрос
Данный:
Таблица назван 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? Что я делаю не так?
Решение
Присоединение к нескольким столбцам в LINQ к 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 состоит из выражений, это будет иметь гораздо больше смысла, под обложками это будет генерировать тип соединения, который вы ищете.
РЕДАКТИРОВАТЬ Добавление примера для второго присоединения на основе комментария.
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 - это поиск двух вещей, присоединяющихся к результатам проекта и продолжайте цепочку
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;
}
В LINQ2SQL вам редко нужно явно присоединиться при использовании внутренних соединений.
Если у вас есть правильные отношения иностранных ключей в вашей базе данных, вы автоматически получите отношение в дизайнере LINQ (если нет, вы можете создать отношение вручную у дизайнера, хотя у вас действительно должны быть надлежащие отношения в вашей базе данных)
Тогда вы можете просто получить доступ к связанным таблицам с помощью «точечного нота»
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
На мой взгляд, это гораздо более читаемо и позволяет вам сосредоточиться на ваших особых условиях, а не на фактической механике соединения.
Редактировать
Это, конечно, применимо только тогда, когда вы хотите присоединиться к линии с нашей моделью базы данных. Если вы хотите присоединиться к «вне модели», вам нужно прибегнуть к ручным соединениям, как в отвечать из Квинтин Робинсон
Вы также можете использовать:
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 }
Я хотел бы привести еще один пример, в котором используются несколько (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
};
Вы также можете присоединиться, если количество столбцов не одинаково в обеих таблицах и может отобразить статическое значение с столбцом таблицы
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}
На мой взгляд, это самый простой способ присоединиться к двум таблицам с несколькими полями:
from a in Table1 join b in Table2
on (a.Field1.ToString() + "&" + a.Field2.ToString())
equals (b.Field1.ToString() + "&" + b.Field2.ToString())
select a
Вы можете написать свой запрос так.
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
Если вы хотите сравнить свой столбец с несколькими столбцами.