【问题标题】:Linq to Sql: Multiple left outer joinsLinq to Sql:多个左外连接
【发布时间】:2010-09-21 00:23:17
【问题描述】:

我在弄清楚如何使用 LINQ to SQL 使用多个左外连接时遇到了一些麻烦。我了解如何使用一个左外连接。我正在使用 VB.NET。下面是我的 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

【问题讨论】:

    标签: vb.net linq linq-to-sql tsql left-join


    【解决方案1】:

    这可能更简洁(您不需要所有 into 语句):

    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
    

    这是另一个左连接示例

    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  
        }
    

    【讨论】:

    • @manitra:不,您实际上得到了 LEFT OUTER JOIN 语句(没有嵌套选择)。很疯狂吧?
    • 我更喜欢这种方法,而不是使用所有的 into 语句。感谢您发布此信息!
    • 这是各种甜蜜。但是:如果有连接,为什么 linq 中没有左连接?什么基于集合的世界只做内部连接?咕噜。
    • 这只是让我脸上露出灿烂的笑容。感谢您提供易于理解的示例。
    • 我试过这个,它比@tvanfosson 的方法慢一个数量级。我不是直接针对数据库执行此操作,而是严格在 linq to objects 中执行此操作。我有相当于 500000 个费用、4000 个 categoryDtos 和 4000 个费用类型Dtos。跑了1分钟。使用 tvanfosson 的语法需要 6 秒。
    【解决方案2】:

    无权访问 VisualStudio(我在我的 Mac 上),但使用来自 http://bhaidar.net/cs/archive/2007/08/01/left-outer-join-in-linq-to-sql.aspx 的信息,您似乎可以执行以下操作:

    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 }
    

    【讨论】:

      【解决方案3】:

      我想出了如何使用 LINQ to SQL 在 VB.NET 中使用多个左外连接:

      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
      

      【讨论】:

        【解决方案4】:

        在VB.NET中使用函数,

        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 
        

        【讨论】:

          【解决方案5】:

          我认为您应该能够按照this 帖子中使用的方法进行操作。它看起来真的很丑,但我认为你可以做两次并得到你想要的结果。

          我想知道这是否真的是您最好使用 DataContext.ExecuteCommand(...) 而不是转换为 linq 的情况。

          【讨论】:

            【解决方案6】:

            我正在为我的应用程序使用这个 linq 查询。如果这符合您的要求,您可以参考这个。在这里,我加入了(左外连接)3 个表。

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

            【讨论】:

              猜你喜欢
              • 2013-06-13
              • 1970-01-01
              • 2011-10-14
              • 1970-01-01
              • 1970-01-01
              • 2010-11-10
              • 2013-09-09
              • 1970-01-01
              相关资源
              最近更新 更多