Linq - Sql: Birden fazla sol dış birleşim


160

Birden fazla sol dış birleştirmek SQL LINQ kullanarak nasıl anlamaya bazı sorun yaşıyorum. Bir sol dış birleştirmenin nasıl kullanılacağını anlıyorum. VB.NET kullanıyorum. Aşağıda benim SQL sözdizimim var.

T-SQL

SELECT
    o.OrderNumber,
    v.VendorName,
    s.StatusName
FROM
    Orders o
LEFT OUTER JOIN Vendors v ON
    v.Id = o.VendorId
LEFT OUTER JOIN Status s ON
    s.Id = o.StatusId
WHERE
    o.OrderNumber >= 100000 AND
    o.OrderNumber <= 200000

Yanıtlar:


247

Bu daha temiz olabilir ( tüm intoifadelere ihtiyacınız yoktur ):

var query = 
    from order in dc.Orders
    from vendor 
    in dc.Vendors
        .Where(v => v.Id == order.VendorId)
        .DefaultIfEmpty()
    from status 
    in dc.Status
        .Where(s => s.Id == order.StatusId)
        .DefaultIfEmpty()
    select new { Order = order, Vendor = vendor, Status = status } 
    //Vendor and Status properties will be null if the left join is null

İşte başka bir sol birleşim örneği

var results = 
    from expense in expenseDataContext.ExpenseDtos
    where expense.Id == expenseId //some expense id that was passed in
    from category 
    // left join on categories table if exists
    in expenseDataContext.CategoryDtos
                         .Where(c => c.Id == expense.CategoryId)
                         .DefaultIfEmpty() 
    // left join on expense type table if exists
    from expenseType 
    in expenseDataContext.ExpenseTypeDtos
                         .Where(e => e.Id == expense.ExpenseTypeId)
                         .DefaultIfEmpty()
    // left join on currency table if exists
    from currency 
    in expenseDataContext.CurrencyDtos
                         .Where(c => c.CurrencyID == expense.FKCurrencyID)
                         .DefaultIfEmpty() 
    select new 
    { 
        Expense = expense,
        // category will be null if join doesn't exist
        Category = category,
        // expensetype will be null if join doesn't exist
        ExpenseType = expenseType,
        // currency will be null if join doesn't exist
        Currency = currency  
    }

12
@manitra: Hayır, aslında LEFT OUTER JOIN ifadeleri alıyorsunuz (iç içe seçim yok). Oldukça çılgın ha?
Amir

6
Bu yaklaşımı tüm ifadeleri kullanmaktan daha çok seviyorum. Bunu gönderdiğiniz için teşekkürler!
Bryan Roth

7
Bu her çeşit tatlı. Ancak: wtf neden bir katılma varsa linq'te sol bir katılma yok? Hangi set temelli dünya sadece iç birleşimler yapar? Grrr.
jcollum

2
Bu sadece yüzüme kocaman bir gülümseme getirdi. İzlemesi kolay örnek için teşekkürler.
nycdan

2
Bunu denedim ve @ tvanfosson'un yönteminden daha yavaş bir büyüklük sırasıydı. Ben doğrudan bir veritabanına karşı değil, kesinlikle nesneler için linq yapıyordu. 500000 gider, 4000 kategoriDtos ve 4000 giderTypeDtos eşdeğeri vardı. Çalışması 1 dakika sürdü. Tvanfosson sözdizimi ile 6 saniye sürer.
Chris


22

Nasıl LINQ to SQL kullanarak VB.NET içinde birden çok sol dış birleşimler kullanmayı anladım:

Dim db As New ContractDataContext()

Dim query = From o In db.Orders _
            Group Join v In db.Vendors _
            On v.VendorNumber Equals o.VendorNumber _
            Into ov = Group _
            From x In ov.DefaultIfEmpty() _
            Group Join s In db.Status _
            On s.Id Equals o.StatusId Into os = Group _
            From y In os.DefaultIfEmpty() _
            Where o.OrderNumber >= 100000 And o.OrderNumber <= 200000 _
            Select Vendor_Name = x.Name, _
                   Order_Number = o.OrderNumber, _
                   Status_Name = y.StatusName

8

VB.NET'te İşlev kullanarak,

Dim query = From order In dc.Orders
            From vendor In 
            dc.Vendors.Where(Function(v) v.Id = order.VendorId).DefaultIfEmpty()
            From status In 
            dc.Status.Where(Function(s) s.Id = order.StatusId).DefaultIfEmpty()
            Select Order = order, Vendor = vendor, Status = status 

3

Bu yayında kullanılan yöntemi takip edebilmeniz gerektiğini düşünüyorum . Gerçekten çirkin görünüyor, ama bunu iki kez yapabileceğinizi ve istediğiniz sonucu elde edebileceğinizi düşünüyorum.

Bu aslında DataContext.ExecuteCommand(...)linq dönüştürmek yerine kullanarak daha iyi olurdu bir durum olup olmadığını merak ediyorum .


0

Benim uygulama için bu linq sorgusu kullanıyorum. Bu gereksiniminizle eşleşiyorsa bunu başvurabilirsiniz. Burada 3 masa ile (Sol dış birleşim) katıldım.

 Dim result = (From csL In contractEntity.CSLogin.Where(Function(cs) cs.Login = login AndAlso cs.Password = password).DefaultIfEmpty
                   From usrT In contractEntity.UserType.Where(Function(uTyp) uTyp.UserTypeID = csL.UserTyp).DefaultIfEmpty ' <== makes join left join
                   From kunD In contractEntity.EmployeeMaster.Where(Function(kunDat) kunDat.CSLoginID = csL.CSLoginID).DefaultIfEmpty
                   Select New With {
                  .CSLoginID = csL.CSLoginID,
                  .UserType = csL.UserTyp}).ToList()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.