tags:

views:

73

answers:

3

Hello.
I need to write the method in C# that will return some specific dictionary from DB. Lets say that data stored in 2 tables looks like:

table Groups (id, name):

1, 'Management'  
2, 'IT Department'  
3, 'Production'  

The Users (id, name, groupId, projectId):

1, 'John', 1, 1  
2, 'Ben',  2, 1  

Now I need to check that in every project every group have no less than one user. The sql query to achieve this information will be:

declare @projectId int;  
set @projectId = 1;  

select g.Name, case when(isnull(u.id,0) > 0) then 1 else 0 end HasUsers  
from groups g  
left join users u  
on g.id = u.groupId and u.projectId = @projectId;  

The information that are returned from this query looks like bellow:

'Management',    1  
'IT Department', 1  
'Production',    0  

What's so special in the query? The condition for projectId is included in 'join' part, not 'where' part. In consequence the row for 'Production' group is returned with value 0. When we move condition for projectId to 'where part' the record will not be present in the return result.

Finally the question - is it possible to achieve similar effect using one lambda expression? (I know that I can achieve 2 collections and using some kind of loop statement get the final result, but it's not a subject of this question)

regards,
yaki

A: 

LINQ Outer Join queries take the form of this:

from x in collection
join y in otherCollection on x.Key equals y.Key into g
from o in g.DefaultIfEmpty()
select new Whatever {
    Something = x,
    Other = o
};

If there is no related y to join to the x, then the o selected from g will be null

Andrew Burgess
Thanx for response. Yes, I know the linq syntax for outer join but it doesn't 'hit' the parameter for projectId (that was very important in this case).
yaki
A: 

Semi shot in the dark:

from g in groups 
join u in users on  
new { a = g.id, b=u.projectid } equals new { a = u.groupid, b = [var_goes_here] } into t 
from u in ps.DefaultIfEmpty() 
select new { GroupName = g.name, HasUsers = u == null ? 0 : 1 };
ThatSteveGuy
+1  A: 

Ok, I think that I figured it out by myself. The sql produced is a little bit more complicated then provided in original post, but the resultset is the same.

var query = db
  .Groups
  .GroupJoin(db.Users.Where(u => u.projectId == 1) , g => g.Id, u => u.groupId, (g, u) => new { u, g })
  .SelectMany(x => x.u.DefaultIfEmpty(), (g,u) => new {Group = g.g, Users = u})
  .Select(res => new {Group = res.Group.Name, Counter = (res.Users != null)});
yaki