2010-10-18 79 views
8

Tôi đang có một thời gian heckuva tìm ra cách dịch một SQL LEFT OUTER JOIN đơn giản với hai điều kiện mà mệnh đề vào một truy vấn LINQ-to-Entities đang hoạt động . Chỉ có hai bảng. Tôi cần các giá trị cho tất cả các hàng từ Table1, bất kể các đối sánh trong Table2, nhưng mệnh đề WHERE sử dụng các trường từ Table2. Trong SQL, hai tham số sẽ Table2WhereColumn1 và Table2WhereColumn2, và truy vấn (mà hoạt động) trông như thế này:LINQ-to-Entities: LEFT OUTER JOIN với mệnh đề WHERE và chiếu

SELECT t1.Table1Id, 
    t1.FieldDescription, 
    t2.FieldValue 
FROM Table1 t1 WITH (NOLOCK) 
LEFT JOIN Table2 t2 WITH (NOLOCK) ON t1.Table1Id = t2.Table1Id 
WHERE (t2.Table2WhereColumn1 = @someId OR t2.Table2WhereColumn1 IS NULL) 
AND (t2.Table2WhereColumn2 = @someOtherId OR t2.Table2WhereColumn2 IS NULL) 
ORDER BY t1.OrderByColumn 

Tôi đã cố gắng sử dụng Group Join với DefaultIfEmpty(), cũng như tiềm ẩn tham gia (không có thực tế Join từ khóa) và tôi chỉ nhận được các hàng cho các mục có giá trị trong Bảng 2. Tôi chắc chắn điều này sẽ không giúp đỡ, nhưng đây là một ví dụ về Linq Tôi đã cố gắng mà không hoạt động:

Public Shared Function GetProfilePreferencesForCedent(ByVal dc As EntityContext, _ 
                 ByVal where1 As Int32, _ 
                 ByVal where2 As Int32) _ 
                As IQueryable(Of ProjectedEntity) 
    Return From t1 In dc.Table1 
      Group Join t2 In dc.Table2 _ 
       On t1.Table1Id Equals t2.Table1Id _ 
       Into t2g1 = Group _ 
      From t2gx In t2g1.DefaultIfEmpty(Nothing) 
      Where (t2gx.Table2Where1 = where1 Or t2gx.Table2Where1 = Nothing) _ 
       And (t2gx.Table2Where2 = where2 Or t2gx.Table2Where2 = Nothing) 
      Order By t1.SortOrder 
      Select New ProjectedEntity With { 
       .Table1Id = t1.Table1Id, _ 
       .FieldDescription = t1.FieldDescription, _ 
       .FieldValue = If(t2gx Is Nothing, String.Empty, t2gx.FieldValue) _ 
      } 
End Function 

Trả lời

10

Hãy truy cập vào các truy vấn này và cho tôi biết nếu chúng phù hợp với bạn. Tôi chưa thiết lập dữ liệu để kiểm tra, nhưng chúng sẽ ổn.

Hãy tha thứ cho sự pha trộn của tôi về C# & VB.NET. Tôi từng là một nhà phát triển VB.NET, nhưng trong vài năm qua tôi đã làm việc chủ yếu trong C#, vì vậy bây giờ tôi cảm thấy thoải mái hơn ở đó.

Dưới đây là các lớp học tôi đã tạo cho Table1 & Table2:

public class Table1 
{ 
    public int Table1Id { get; set; } 
    public string FieldDescription { get; set; } 
    public int OrderByColumn { get; set; } 
} 
public class Table2 
{ 
    public int Table1Id { get; set; } 
    public string FieldValue { get; set; } 
    public int Table2WhereColumn1 { get; set; } 
    public int Table2WhereColumn2 { get; set; } 
} 

Bây giờ các truy vấn trong C# nên là:

var query = 
    from t1 in Table1 
    join t2 in Table2 on t1.Table1Id equals t2.Table1Id into _Table2 
    from _t2 in _Table2.DefaultIfEmpty() 
    where _t2 == null ? true : 
     _t2.Table2WhereColumn1 == @someId 
     && _t2.Table2WhereColumn2 == @someOtherId 
    orderby t1.OrderByColumn 
    select new 
    { 
     t1.Table1Id, 
     t1.FieldDescription, 
     FieldValue = _t2 == null ? "" : _t2.FieldValue, 
    }; 

Và bản dịch sang VB.NET:

Dim query = _ 
    From t1 In Table1 _ 
    Group Join t2 In Table2 On t1.Table1Id Equals t2.Table1Id Into _Table2 = Group _ 
    From _t2 In _Table2.DefaultIfEmpty() _ 
    Where If(_t2 Is Nothing, True, _t2.Table2WhereColumn1 = someId AndAlso _ 
            _t2.Table2WhereColumn2 = someOtherId) _ 
    Order By t1.OrderByColumn _ 
    Select New With { _ 
      .Table1Id = t1.Table1Id, _ 
      .FieldDescription = t1.FieldDescription, _ 
      .FieldValue = If(_t2 Is Nothing, "", _t2.FieldValue) _ 
     } 

Hãy cho tôi biết nếu chúng hoạt động. Ngón tay vượt qua. :-)

+0

nổi bật! Làm việc như một say mê. Tôi không chắc tôi hiểu cách mệnh đề Where hoạt động, nhưng nó hoạt động. –

3

Cá nhân nếu có điều kiện cho phía bên tay phải của một trái tham gia Tôi thường thích để đặt chúng vào các tiêu chuẩn tham gia

Trong trường hợp này SQL sẽ trông như thế:

SELECT t1.Table1Id, 
     t1.FieldDescription, 
     t2.FieldValue 
FROM Table1 t1 WITH (NOLOCK) 
LEFT JOIN Table2 t2 WITH (NOLOCK) ON t1.Table1Id = t2.Table1Id 
            AND t2.Table2WhereColumn1 = @someId 
            AND t2.Table2WhereColumn2 = @someOtherId 
ORDER BY t1.OrderByColumn 

mã LINQ cho điều này (trong C#) sẽ như thế nào:

var query = 
    from t1 in Table1 
    join t2 in Table2 on new{a = t1.Table1Id, b = someId, c = someotherId} 
         equals new {a = t2.Table1Id b = t2.Table2WhereColumn1, c = Table2WhereColumn2} 
    into _Table2 
    from _t2 in _Table2.DefaultIfEmpty() 
    orderby t1.OrderByColumn 
    select new 
    { 
     t1.Table1Id, 
     t1.FieldDescription, 
     FieldValue = _t2 == null ? "" : _t2.FieldValue, 
    }; 

không kiểm tra nó - nhưng nên làm việc

+0

+1 Đây là cách tôi muốn tạo bảng đúng LINQ, nơi điều kiện trên một bên ngoài bên ngoài tham gia như tôi cảm thấy nó đọc nhiều hơn tương tự như cú pháp Sql tôi đang sử dụng để. –

+0

Cú pháp thực sự tốt đẹp. Tôi phải đồng ý về cảm giác giống SQL hơn. – Tobias

0

tôi sẽ không mất tín dụng cho câu trả lời này nhưng nó tuyệt đẹp: LINQ to SQL - Left Outer Join with multiple join conditions

Về cơ bản, sử dụng phần mở rộng phương pháp mệnh đề where trên subquery nhưng bạn phải sử dụng nó trước khi DefaultIfEmpty():

from p in context.Periods 
join f in context.Facts on p.id equals f.periodid into fg 
from fgi in fg.Where(f => f.otherid == 17).DefaultIfEmpty() 
where p.companyid == 100 
select f.value 
Các vấn đề liên quan