Left outer Join in LINQ con due condizioni

Non ho trovato molti esempi su come impostare una query Linq2Sql che abbia una Left Outer join con due (o più) condizioni all'interno della join; mi segno quindi qui come penso sia corretto fare:

Supponiamo di avere una tabella Employees (impiegati), una Groups (gruppi) e una JoinEmployeesGroups che mi tenga la relazione molti a molti. Voglio tirare fuori tutti i gruppi, ovvero idGroup e GroupName e una terza colonna che mi indichi se un determinato impiegato è associato a quel gruppo (il classico caso di binding ad una checkboxlist ad esempio).

In Sql, per ottenere ad esempio i gruppi a cui è associato l'impiegato 12, farei:
SELECT  g.idGroup,
        g.GroupName,
        ( CASE
          WHEN j.idEmployee IS NOT NULL THEN 1
          ELSE 0
          END ) AS Selected
FROM    Groups AS g
LEFT OUTER JOIN JoinEmployeesGroups AS j ON ( g.idGroup = j.idGroup ) AND ( j.idEmployee = 12 )
ORDER BY GroupName

ottenendo

idGroup    GroupName       Selected
---------- --------------- -----------
MAG        Magazzino       0
MGMT       Management      1
MANUF      Manufacturing   0
PROC       Procurement     0
HWDEV      Progettisti HW  0
SWDEV      Progettisti SW  1

Come tradurla in Linq to Sql ?

var qgroup =   from g in db.Groups
               join j in db.JoinEmployeesGroups.Where( p => p.idEmployee == 12) on g.idGroup equals j.idGroup  into jg
               from x in jg.DefaultIfEmpty()
               orderby g.GroupName
               select new { g.idGroup, g.GroupName, Selected = (x.idEmployee != null) };

La parte blu è quella "tricky" (parola grossa, era ovvio che si facesse così)... Ma dove metterla ? Alla fine non cambia praticamente niente se la mettiamo nella parte della join o nella seconda from (verificato con la query sql che genera)

var qgroup =   from g in db.Groups
               join j in db.JoinEmployeesGroups on g.idGroup equals j.idGroup  into jg
               from x in jg.Where( p => p.idEmployee == 12).DefaultIfEmpty()
               orderby g.GroupName
               select new { g.idGroup, g.GroupName, Selected = (x.idEmployee != null) };

Come bindare alla checkboxlist e selezionare gli item giusti è poi banale 

cblGroups.DataSource = qgroup;
cblGroups.DataTextField = "GroupName";
cblGroups.DataValueField = "idGroup";
cblGroups.DataBind();
foreach (var gr in qgroup)
{
    ListItem li = cblGroups.Items.FindByValue(gr.idGroup);
    li.Selected = gr.Selected;
}

Ogni giorno mi innamoro sempre di più di LINQ... :-)

Published 11 giugno 2008 05.11 by Sandro
Filed under:

Comments

# Marco Russo said on 17 giugno, 2008 11.56
Il tuo post mi ha dato lo spunto per un post sull'argomento - dai un'occhiata perché se puoi è meglio usare una relazione implicita piuttosto che usare una join esplicita. http://introducinglinq.com/blogs/marcorusso/archive/2008/06/18/to-join-or-not-to-join-that-is-the-question-in-linq.aspx

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:

Search

Go

This Blog

Add to Technorati Favorites

Syndication