Il blog di Sandro Rizzetto

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... :-)

Commenti (1) -

Aggiungi Commento

Copyright © 1997-2017 Sandro Rizzetto | All Rights Reserved | Riproduzione delle fotografie vietata | Powered by me