Reputation: 6554
I have the below tables that are coming from my SQL Database with Entity Framework 5.
What I want to do is select all users where tblUserBusiness.BUID equals a passed in value OR where the Users.IsSysAdmin equals True. If the Users.IsSysAdmin equals True there will be no relating tblUserBusiness records hence the Left Outer Join.
I started with the below LINQ query that filtered correctly but did not allow for the Outer Join
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
Then I moved onto the below query which allows for the Outer Join but I have no idea how to implement the 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
Basically what I am after is the LINQ equivalent to the below TSQL
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)
Upvotes: 2
Views: 1710
Reputation: 968
+1 for @ajakblackgoat answer. Thanks bro, it helped me! However I am a C# developer so posting a C# version for other developers similar to me, if they land on this page :)
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))
tried to post in comments but full code wasn't showing properly
Upvotes: 0
Reputation: 2149
Try this:
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
... or...
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
Either one will give you what you need. I think :)
Upvotes: 2
Reputation: 26424
You need to be using DefaultIfEmpty, so it should be
Group Join bu In db.tblUserBusinesses.DefaultIfEmpty
Here is a reduced test case (requires a brand new Console Application):
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
While this may not be the ideal design for a Person-to-Address relationship, it proves that Outer Join
can work in VB.NET using DefaultIfEmpty
and FirstOrDefault
(which is optional, helps organize your data in a nice fashion).
Upvotes: 0