161 votes

Linq to Sql : Jointures externes multiples à gauche

J'ai du mal à comprendre comment utiliser plus d'une jointure externe gauche en utilisant LINQ to SQL. Je comprends comment utiliser une seule jointure externe gauche. J'utilise VB.NET. Voici ma syntaxe SQL.

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

249voto

Amir Points 5816

Cela peut être plus propre ( vous n'avez pas besoin de tous les into déclarations ) :

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

Voici un autre exemple de jointure gauche

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  
    }

1 votes

A quoi ressemble le SQL généré ? Ne contient-il pas des selects imbriqués de cette façon ?

12 votes

@manitra : Non, vous obtenez en fait des instructions LEFT OUTER JOIN (pas de sélections imbriquées). C'est assez fou, non ?

6 votes

Je préfère cette approche à l'utilisation de toutes les instructions into. Merci d'avoir publié cet article !

49voto

tvanfosson Points 268301

Je n'ai pas accès à VisualStudio (je suis sur mon Mac), mais en utilisant l'information de http://bhaidar.net/cs/archive/2007/08/01/left-outer-join-in-linq-to-sql.aspx il semble que vous puissiez faire quelque chose comme ça :

var query = from o in dc.Orders
            join v in dc.Vendors on o.VendorId equals v.Id into ov
            from x in ov.DefaultIfEmpty()
            join s in dc.Status on o.StatusId equals s.Id into os
            from y in os.DefaultIfEmpty()
            select new { o.OrderNumber, x.VendorName, y.StatusName }

22voto

Bryan Roth Points 3592

J'ai trouvé comment utiliser des jointures externes multiples à gauche dans VB.NET en utilisant LINQ to SQL :

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

8voto

Mitul Points 2757

En VB.NET en utilisant Function,

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

3voto

Jon Norton Points 2048

Je pense que vous devriez être en mesure de suivre la méthode utilisée en este poste. C'est vraiment moche, mais je pense que vous pouvez le faire deux fois et obtenir le résultat que vous voulez.

Je me demande si ce n'est pas un cas où vous feriez mieux d'utiliser DataContext.ExecuteCommand(...) au lieu de le convertir en linq.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X