LINQ to SQL: Nhiều tham gia TRÊN nhiều cột. Điều này có thể không?


131

Được:

Một bảng có tên TABLE_1với các cột sau:

  • ID
  • ColumnA
  • ColumnB
  • ColumnC

Tôi có SQL truy vấn nơi TABLE_1tham gia vào bản thân hai lần dựa tắt của ColumnA, ColumnB, ColumnC. Truy vấn có thể trông giống như thế này:

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.

Vấn đề:

Tôi cần Truy vấn đó để được viết lại trong LINQ. Tôi đã thử đâm vào nó:

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 :(

Làm cách nào để viết truy vấn của tôi trong LINQ? Tôi đang làm gì sai?

Câu trả lời:


241

Tham gia vào nhiều cột trong Linq to SQL có một chút khác biệt.

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

Bạn phải tận dụng các loại ẩn danh và soạn một loại cho nhiều cột bạn muốn so sánh với.

Điều này thoạt nghe có vẻ khó hiểu nhưng một khi bạn đã làm quen với cách SQL được tạo từ các biểu thức thì nó sẽ có ý nghĩa hơn rất nhiều, dưới vỏ bọc này sẽ tạo ra kiểu tham gia mà bạn đang tìm kiếm.

EDIT Thêm ví dụ cho tham gia thứ hai dựa trên nhận xét.

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
điều này làm việc tuyệt vời cho hai tham gia. Tôi cần nó để làm việc với BA tham gia. Xin lỗi, khối mã thứ hai là một chút sai lệch.
aarona

46
Nếu bạn gặp lỗi trình biên dịch về suy luận kiểu, hãy kiểm tra hai điều, (1) là các kiểu giống nhau và (2) là các tên cột giống nhau. Phần tên là một gotcha. Ví dụ này sẽ không biên dịch ngay cả khi tất cả các cột là varchars join T2 in db.tbl2 on new { T1.firstName, T1.secondName } equals new { T2.colFirst, T2.colSecond }. Tuy nhiên, nếu bạn thay đổi nó thành cái này, nó sẽ biên dịch, tuy nhiênjoin T2 in db.tbl2 on new { N1 = T1.firstName, N2 = T1.secondName } equals new { N1 = T2.colFirst, N2 = T2.colSecond }
user2023861

4
Đặt tên vấn đề có thể được loại bỏ bằng từ t1 trong myTABLE1List tham gia t2 trong myTABLE1List trên mới {Cola = t1.ColumnA, colB = t1.ColumnB} bằng mới {Cola = t2.ColumnA, colBBt2.ColumnB}
Baqer Naqvi

1
vui lòng cho phép tôi chỉnh sửa ví dụ, vì nó cần gán cho các thuộc tính ẩn danh
AceMark 24/07/2015

1
Có gì đó không đúng ở đây .. với LINQ. Tôi có thể tham gia trên nhiều bảng, tôi có thể tham gia trên nhiều lĩnh vực ... tuy nhiên, tôi không thể làm điều đó cho cả hai, như ví dụ hiển thị ở đây. Vì vậy, giả sử bạn chỉ có một tham gia trên 1 lĩnh vực .. và bạn có một tham gia thứ 2 theo sau nó. Nếu bạn thay đổi liên kết thứ nhất (hoặc cả hai) thành chỉ sử dụng {x.field} mới bằng {y.field} mới thì có lỗi trình biên dịch. Về mặt chức năng, bạn không thay đổi bất cứ điều gì. Sử dụng .Net 4.6.1.
dùng2415376

12

Trong LINQ2Query, bạn hiếm khi cần tham gia một cách rõ ràng khi sử dụng các phép nối bên trong.

Nếu bạn có các mối quan hệ khóa ngoại thích hợp trong cơ sở dữ liệu của mình, bạn sẽ tự động nhận được mối quan hệ trong trình thiết kế LINQ (nếu không bạn có thể tạo mối quan hệ theo cách thủ công trong trình thiết kế, mặc dù bạn thực sự cần có quan hệ đúng trong cơ sở dữ liệu của mình)

quan hệ cha mẹ và con cái

Sau đó, bạn chỉ có thể truy cập các bảng có liên quan với "ký hiệu chấm"

var q = from child in context.Childs
        where child.Parent.col2 == 4
        select new
        {
            childCol1 = child.col1,
            parentCol1 = child.Parent.col1,
        };

sẽ tạo truy vấn

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

Theo tôi điều này dễ đọc hơn nhiều và cho phép bạn tập trung vào các điều kiện đặc biệt của bạn chứ không phải các cơ chế thực tế của việc tham gia.

Chỉnh sửa
Điều này tất nhiên chỉ áp dụng khi bạn muốn tham gia vào dòng với mô hình cơ sở dữ liệu của chúng tôi. Nếu bạn muốn tham gia "bên ngoài mô hình", bạn cần phải sử dụng các tham gia thủ công như trong câu trả lời từ Quintin Robinson


11

Title_Authors là một tìm kiếm hai điều tham gia tại một kết quả dự án thời gian và tiếp tục chuỗi

        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

Bạn cũng có thể sử dụng:

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
À !! Những công việc này! Và điều KHÁC BIỆT, là bạn cần thực hiện phần "ColA =" để trong phần khác tham gia cùng một lĩnh vực. Trong nhiều năm tôi đã không làm điều đó, nhưng cũng chỉ cần 1 người tham gia trên nhiều lĩnh vực. Nhưng bây giờ tôi cần nhiều hơn và nó CHỈ LÀM VIỆC nếu tôi gán tên biến cho các trường như trong ví dụ này.
dùng2415376

3

Tôi muốn đưa ra một ví dụ khác trong đó nhiều (3) phép nối được sử dụng.

 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
Không giống nhau - câu hỏi là về việc nối các bảng dựa trên nhiều cột trong mỗi cột, không nối nhiều bảng dựa trên một cột trong mỗi cột.
bộ

1

Bạn cũng có thể tham gia nếu số lượng cột không giống nhau trong cả hai bảng và có thể ánh xạ giá trị tĩnh vào cột bảng

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

Theo tôi, đây là cách đơn giản nhất để tham gia hai bảng có nhiều trường:

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

Trong SQL, làm điều này sẽ chậm hơn đáng kể so với việc tham gia trên từng cột riêng biệt (mặc dù vẫn sẽ khá nhanh nếu tập dữ liệu không lớn). Có lẽ linq sẽ tạo ra SQL rõ ràng, vì vậy hãy ghi nhớ hiệu suất nếu bạn sử dụng giải pháp này.
EGP

-10

Bạn có thể viết truy vấn của bạn như thế này.

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

Nếu bạn muốn so sánh cột của bạn với nhiều cột.


1
@ user658720 Chào mừng bạn đến với StackOverFlow :). Tôi sẽ đề nghị bạn định dạng mã cho bạn để dễ đọc hơn. Bạn có thể chọn văn bản và nhấp vào nút mã trên trình chỉnh sửa.
aarona
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.