【问题标题】:LINQ Left Outer Join with conditions带有条件的 LINQ 左外连接
【发布时间】:2013-06-13 14:47:53
【问题描述】:

下面的表格来自我的带有 Entity Framework 5 的 SQL 数据库。

我想要做的是选择 tblUserBusiness.BUID 等于传入值或 Users.IsSysAdmin 等于 True 的所有用户。如果 Users.IsSysAdmin 等于 True,则不会有相关的 tblUserBusiness 记录,因此是 Left Outer Join。

我从以下 LINQ 查询开始,该查询正确过滤但不允许外部联接

        businessUsers = (From u In db.Users
                            From bu In db.tblUserBusinesses
                            Where bu.BUID.Equals(buID) Or u.IsSysAdmin.Equals(True)
                                Select New Users With {.ID = u.ID,
                                                       .Name = u.Name,
                                                       .UserName = u.UserName}).ToList

然后我转到以下允许外部联接的查询,但我不知道如何实现 Where bu.BUID.Equals(buID) Or u.IsSysAdmin.Equals(True)

        businessUsers = (From u In db.Users
                            Group Join bu In db.tblUserBusinesses
                                On u Equals bu.User
                                Into userList = Group
                         Select New Users With {.ID = u.ID,
                                                       .Name = u.Name,
                                                       .UserName = u.UserName}).ToList

基本上我所追求的是相当于以下 TSQL 的 LINQ

SELECT Users.ID, Users.UserName, Users.Name 
    FROM Users LEFT OUTER JOIN tblUserBusiness ON Users.ID = tblUserBusiness.UserID
    WHERE (Users.IsSysAdmin = 1) OR (tblUserBusiness.BUID = 5)

【问题讨论】:

    标签: .net vb.net linq linq-to-entities


    【解决方案1】:

    试试这个:

    Dim buID As Integer = ... ' BUID to get
    
    Dim q = From u In Users
            Group Join bu In tblUserBusiness On u.Id Equals bu.UserID Into Group
            From j In Group.DefaultIfEmpty
            Where u.IsSysAdmin OrElse If(j IsNot Nothing, j.BUID = buID, False)
            Select u
    

    ...或者...

    Dim q = From u In Users
            Group Join bu In tblUserBusiness On u.Id Equals bu.UserID Into Group
            From j In Group.Where(Function(x) x.BUID = buID).DefaultIfEmpty
            Where u.IsSysAdmin OrElse j IsNot Nothing
            Select u
    

    任何一个都可以满足您的需求。我认为:)

    【讨论】:

    • +1。谢谢,它帮助了我!但是,我是 C# 开发人员,因此如果其他与我类似的开发人员登陆此页面,请发布 C# 版本:)
    【解决方案2】:

    你需要使用DefaultIfEmpty,所以应该是

    Group Join bu In db.tblUserBusinesses.DefaultIfEmpty
    

    这是一个简化的测试用例(需要全新的控制台应用程序):

    Module Module1
      Class Person
        Public Property Id As String
        Public Property FirstName As String
      End Class
    
      Class Address
        Public Property Id As String
        Public Property StreetName As String
      End Class
    
      Sub Main()
        Dim personList As New List(Of Person)
        With personList
          .Add(New Person With {.Id = "1", .FirstName = "John"})
          .Add(New Person With {.Id = "2", .FirstName = "Peter"})
          .Add(New Person With {.Id = "3", .FirstName = "Victor"})
        End With
    
        Dim addressList As New List(Of Address)
        With addressList
          .Add(New Address With {.Id = "1", .StreetName = "Baker Street"})
          .Add(New Address With {.Id = "2", .StreetName = "Broadway"})
          .Add(New Address With {.Id = "4", .StreetName = "Hwy 999"})
        End With
    
        Dim v = From p In personList
                Group Join a In addressList.DefaultIfEmpty
                On a.Id Equals p.Id Into Group
                Select PersonId = p.Id,
                       PersonName = p.FirstName,
                       StreetName = Group.FirstOrDefault
      End Sub
    End Module
    

    虽然这可能不是个人到地址关系的理想设计,但它证明Outer Join 可以使用DefaultIfEmptyFirstOrDefault 在VB.NET 中工作(这是可选的,有助于在不错的时尚)。

    【讨论】:

    • 那行不通。例如,如果我有两个 IsSysAdmin = false 的用户记录,其中只有一个用户有匹配的 tblUserBusinesses 记录,则返回两个用户记录。
    • @PhilMurray:它应该是 MSDN 上推荐的 outer join 的做法。不幸的是,如果没有简化的测试用例,我就无法进行测试。你能在你的问题中添加一个吗? IE。可以将其复制到全新的控制台或 winforms 应用程序,以便重现问题。
    【解决方案3】:

    +1 @ajakblackgoat 答案。谢谢老哥,对我有帮助!但是,我是 C# 开发人员,因此如果其他与我类似的开发人员登陆此页面,则发布 C# 版本 :)

    from u in Users
    join bu in tblUserBusiness on u.Id equals bu.UserID into group
    from j in group.DefaultIfEmpty()
    where (u.IsSysAdmin || (j != null ? j.BUID == buID : false))
    

    尝试在 cmets 中发布,但完整代码未正确显示

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 2020-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      相关资源
      最近更新 更多