Linq to Sql – Remplir le résultat JOIN dans une liste

Je ne sais pas si cela peut être fait, mais voici le scénario.

Je veux transformer ce sql en linq:

SELECT * FROM Department d INNER JOIN Employee e ON e.DepartmentID = d.DepartmentID 

Département – L’employé a une relation de 1 à plusieurs.

J’ai créé un object personnalisé dans lequel j’aimerais remplir le résultat.

 public class DepartmentSummary { public Department Department { get; set; } public List Employees {get; set;} } 

Le Linq que je suis venu avec est

 var result = from d in dba.Department join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1 select new DepartmentSummary { Department = d, Employees = j1.ToList() }; 

Je l’ai essayé et ça ne marche pas. Quelqu’un peut-il m’éclairer s’il vous plait? Je voudrais effectuer une jointure interne entre le département et l’employé. Pour chaque département du jeu de résultats, j’aimerais créer un object DepartmentSummary contenant ce département et une liste des employés appartenant à ce département.

Linq fournit-il une solution ad hoc à cet effet ou dois-je parcourir le jeu de résultats et créer manuellement une liste de DepartmentSummary?

Merci,

EDIT: On dirait que ça marche pour moi

 var result = from d in dba.Department join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1 where j1.Count() > 0 select new DepartmentSummary { Department = d, Employees = j1.ToList() }; 

On dirait que vous cherchez à vous déplacer paresseux?

 DataLoadOptions dlo = new DataLoadOptions(); dlo.LoadWith(d => d.Employees); using (var dba = new MyDataContext()) { dba.LoadOptions = dlo; var result = from d in dba.Department select d; } 

Désormais, si vous n’avez pas défini de relation entre service et employés (le concepteur Linq2Sql le fera pour vous si vous avez configuré les relations avec la firebase database), vous devriez alors envisager de le faire. Cela facilite considérablement les choses. En fait, vous n’avez même pas besoin du résumé de votre campagne.

Le fait est que vous ne prenez pas vraiment un SQL et essayez de créer une requête Linq à partir de celui-ci.

Si vous l’étiez, vous remarquerez que votre requête SQL ne produit pas réellement une ligne par service, mais répète les informations du service pour chaque employé de ce service.

Maintenant, un premier coup d’oeil naïf suggèrerait que vous utilisiez une clause group-by, car cela vous permettrait de fractionner les données en groupes individuels pour chaque service, mais les regroupements en SQL ne vous donnent pas vraiment un type clé + tout-correspondance-lignes de résultat, cela vous permet plutôt de faire des calculs globaux, comme “pour chaque département, combien d’employés ai-je”.

Donc, pour faire ce que vous voulez, vous devez faire une jointure normale, ce qui vous donnera chaque employé, associé aux informations du service approprié (c.-à-d. Que chaque employé sera lié à son service), puis vous besoin de construire le rest de la structure de données vous-même.

Cela dit, si vous avez les relations appropriées définies dans vos classes liées au contexte de données, chaque service devrait déjà posséder une sorte de propriété contenant tous les employés de ce service. La requête peut donc être simplement “donnez-moi tous les services”. et puis vous pouvez, pour chaque département, récupérer les employés?

Bien sûr, cela exécuterait probablement un code SQL pour chaque service, mais dans ce cas, vous êtes de nouveau obligé de me “donner tous les employés avec leurs informations de service” et vous devez générer du code pour gérer le rest.

LINQ to SQL ne comprend pas votre appel ToList() , mais vous pourrez peut-être sélectionner la séquence des éléments joints, puis utiliser LINQ to Objects (via AsEnumerable() ) pour mapper votre object DepartmentSummary :

 var qResult = from d in dba.Department join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1 select new { Department = d, Employees = j1 }; var result = from d in qResult.AsEnumerable() select new DepartmentSummary() { Department = d.Department, Employees = e.Employees.ToList() }; 

Ce problème est dû à la nature de la requête. Lorsque vous rejoignez un service à un autre, vous récupérez un enregistrement pour chaque employé. Cela signifie que votre instruction ToList () attend plusieurs employés par service, mais en raison de la jointure, en obtient toujours un.

Changez votre requête en

 var result = from d in dba.Department select new tCampaignSummary { Department = d, Employees = dba.Employee.Where(e => e.DepartmentID == d.DepartmentID).ToList() }; 

J’ai testé cela et ça marche.

Ce qui est différent, c’est de ne sélectionner qu’un seul enregistrement par département (et non par employé). Le nombre d’employés correspondants est alors nul pour plusieurs départements et converti en liste.

Bonne chance!

EDIT Comme demandé, voici le SQL généré:

 SELECT [t0].*, [t1].* ( SELECT COUNT(*) FROM [dbo].[Employee] AS [t2] WHERE [t2].[DepartmentID] = [t0].[DepartmentID] ) AS [value] FROM [dbo].[Department] AS [t0] LEFT OUTER JOIN [dbo].[Employee] AS [t1] ON [t1].[DepartmentID] = [t0].[DepartmentID] ORDER BY [t0].[DepartmentID], [t1].[IndexID] 

La seule modification est que LINQ ne fera pas [t0]. *, Mais énumérera chaque champ. Comme je devais deviner les champs, je les ai laissés de côté pour clarifier le code SQL.