LINQ до SQL: декілька приєднується до декількох стовпців. Чи можливо це?


131

Подано:

Таблиця 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? Що я роблю неправильно?

Відповіді:


242

Приєднання декількох стовпців у 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 з виразів, це матиме набагато більше сенсу, під обкладинками це генерує тип з'єднання, який ви шукаєте.

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 }
    ...

4
це чудово працює за два приєднання. Мені це потрібно для роботи з ТРИМ приєднаннями. Вибачте, другий блок коду був трохи оманливим.
aarona

46
Якщо ви отримаєте помилку компілятора щодо умовиводу типу, перевірте дві речі, (1) чи типи однакові, і (2) назви стовпців однакові. Частина імен - готча. Цей приклад не збирається, навіть якщо всі стовпці є вархарами join T2 in db.tbl2 on new { T1.firstName, T1.secondName } equals new { T2.colFirst, T2.colSecond }. Якщо ви зміните це на це, воно буде компілюватися, протеjoin T2 in db.tbl2 on new { N1 = T1.firstName, N2 = T1.secondName } equals new { N1 = T2.colFirst, N2 = T2.colSecond }
user2023861

4
Проблему з іменуванням можна усунути за допомогою t1 в myTABLE1 Списку приєднання t2 до myTABLE1List на новому {colA = t1.ColumnA, colB = t1.ColumnB} дорівнює новому {colA = t2.ColumnA, colBBt2.ColumnB}
Baqer Naqvi

1
дозвольте мені відредагувати приклад, оскільки йому потрібні були призначення анонімних ресурсів
AceMark

1
Щось тут не так .. з LINQ. Я можу приєднатися до декількох таблиць, я можу приєднатися до кількох полів ... однак, я не можу зробити це для обох, як показано на прикладі. Отже, скажіть, що у вас просто є з'єднання на 1 полі .. і у вас є 2-е приєднання за ним. Якщо ви змінили перше з'єднання (або обидва), щоб просто використовувати новий {x.field} дорівнює новому {y.field}, є помилка компілятора. Функціонально ви нічого не змінили. Використання .Net 4.6.1.
user2415376

12

У 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

На мою думку, це набагато читабельніше і дозволяє зосередитись на ваших особливих умовах, а не на власній механіці з'єднання.

Редагувати
Це, звичайно, застосовується лише тоді, коли ви хочете приєднатись до лінії нашої моделі бази даних. Якщо ви хочете приєднатися до «поза моделлю» вам необхідно звернутися до керівництва включається як в відповідь від Quintin Robinson


11

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;
        }

10

Ви також можете використовувати:

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
AHHH !! Це працює! А КЛЮЧОВА РІЗНАННЯ полягає в тому, що вам потрібно виконати частину "ColA =", щоб в іншому приєднатися було те саме поле. Роками я цього не робив, але також мені просто знадобиться 1 приєднання на кількох полях. Але зараз мені потрібно більше, і це ТІЛЬКИ РОБОТИ, якщо я призначу ім’я змінної полям, як у цьому прикладі.
користувач2415376

3

Я хотів би навести ще один приклад, у якому використовується кілька (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
                  };

9
Не одне і те ж - питання полягає в об'єднанні таблиць на основі декількох стовпців у кожному, а не в об'єднанні декількох таблиць на основі одного стовпця в кожному.
Ізохронний

1

Ви також можете приєднатися, якщо кількість стовпців не однакова в обох таблицях і може зіставити статичне значення в стовпчик таблиці

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}

-6

На мою думку, це найпростіший спосіб об’єднати дві таблиці з декількома полями:

from a in Table1 join b in Table2    
       on (a.Field1.ToString() + "&" + a.Field2.ToString())     
       equals  (b.Field1.ToString() + "&" + b.Field2.ToString())  
     select a

У SQL це робити буде значно повільніше, ніж приєднання до кожного стовпця окремо (хоча все-таки буде досить швидко, якщо набір даних не великий). Імовірно, linq створить очевидний SQL, тому майте на увазі продуктивність, якщо ви використовуєте це рішення.
EGP

-10

Ви можете написати свій запит так.

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

Якщо ви хочете порівняти свою колонку з кількома стовпцями.


1
@ user658720 Ласкаво просимо до StackOverFlow :). Я б запропонував відформатувати код, щоб його було легше читати. Ви можете вибрати текст і натиснути кнопку коду в редакторі.
aarona
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.