Reputation: 665
I explore a lot and came to know that there is no direct way to apply left join in LINQ. So I got to know that use cross join for the same and then filter the records.
I tried applying that, but still not getting all the records from the left.
Here is my trial:
List<UserAttendanceHistory> lstUserAttendanceHistory = (from registeredAppUser in registeredAppUsers
from userAttendanceHistory in lstUserAttendance.DefaultIfEmpty()
where registeredAppUser.EmailID == userAttendanceHistory.EmailID
//on userAttendanceHistory.EmailID equals registeredAppUser.EmailID
select new UserAttendanceHistory()
{
ContactName = registeredAppUser.ContactName,
EmailID = userAttendanceHistory.EmailID,
Status = userAttendanceHistory.Status
}).ToList();
I have 6 records in lstUserAttendance and 11 records in registeredAppUsers. I want all 11 records from registeredAppUsers in the output.
I know there are lots of questions available similar to this, but I posted this because I am not able to figure it out.
Any help is greatly appreciated.
Upvotes: 0
Views: 42
Reputation: 205579
As described in join clause (C# Reference), the left join pattern in LINQ is like this
from a in A
join b in B on keys(a) equals keys(b) into aBs
from b in aBs.DefaultIfEmpty()
//...
Applying it to your query:
var lstUserAttendanceHistory = (
from registeredAppUser in registeredAppUsers
join userAttendanceHistory in lstUserAttendance
on registeredAppUser.EmailID equals userAttendanceHistory.EmailID
into registeredAppUserHistory
from userAttendanceHistory in registeredAppUserHistory.DefaultIfEmpty()
select new UserAttendanceHistory()
{
ContactName = registeredAppUser.ContactName,
EmailID = userAttendanceHistory.EmailID,
Status = userAttendanceHistory.Status
})
.ToList();
Upvotes: 1
Reputation: 3229
It is a bit convoluted. My approach is to do a Group Join where the right side (the universal segment, or Users) is the key and the left side (the conditional segment, or attendance history) is the grouped elements. SelectMany then projects a list of lists out into a single result.
var userAttendanceHistory =
registeredAppUsers.GroupJoin(lstUserAttendance,
rAU=>rAu.EmailID,
lUA=>lUA.EmailId,
(u,a) => new {user=u, attend=a})
.SelectMany(anonType=> anonType.DefaultIfEmpty(),
(us,at) => new UserAttendanceHistory() {ContactName = us.ContactName,
EmailID = us.EmailID,
Status = at == null ? "Not attended": at.Status
}).ToList();
Upvotes: 2