Question

Etant donné un EmployeeId, comment puis-je construire une requête Linq vers SQL pour rechercher tous les ancêtres de l'employé? Chaque EmployeeId a un SupervisorId associé (voir ci-dessous).

Par exemple, une requête des ancêtres pour EmployeeId 6 (Frank Black) devrait renvoyer Jane Doe, Bob Smith, Joe Bloggs et Head Honcho.

Si nécessaire, je peux mettre en cache la liste de tous les employés pour améliorer les performances.

UPDATE:

J'ai créé la méthode brute suivante pour accomplir la tâche. Il traverse la relation employé.Supervisor jusqu'au nœud racine. Cependant, cela déclenchera un appel de base de données pour chaque employé. Quelqu'un a une méthode plus succincte ou plus performante? Merci.

private List<Employee> GetAncestors(int EmployeeId)
{
    List<Employee> emps = new List<Employee>();
    using (L2STestDataContext dc = new L2STestDataContext())
    {
        Employee emp = dc.Employees.FirstOrDefault(p => p.EmployeeId == EmployeeId);
        if (emp != null)
        {
            while (emp.Supervisor != null)
            {
                emps.Add(emp.Supervisor);
                emp = emp.Supervisor;
            }
        }
    }
    return emps;
}
Était-ce utile?

La solution

Tout d'abord, vous pouvez utiliser les requêtes hiérarchiques de mon projet de méthodes d'extension LINQ . Je pense que cela peut aider à simplifier votre code.

Le problème ici est que cela va créer un appel à la base de données pour chaque noeud de la hiérarchie. Dans le cas de votre exemple, vous aurez 5 allers-retours vers la base de données.

Je choisirais un chemin différent et créerais une procédure stockée pour le faire pour moi et renverrais l’ensemble des objets Employee . Puisque vous déconnectez les objets avant de les renvoyer (en supprimant le contexte), vous pouvez simplement créer un nouvel objet à partir de l'ensemble de résultats de la procédure stockée.

Autres conseils

Une solution simple qui évite de charger la totalité de la table des employés (mais dont la profondeur de parcours est limitée) est la suivante:

var emps = dc.Employees.Where(e => (e.EmployeeId == EmployeeId) ||
                                   (e.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.Supervisor.SupervisorId == EmployeeId) ||
                                   ...);

Enfin, vous devez utiliser une expression de table commune pour aplatir la hiérarchie, mais LINQ to SQL ne le supporte pas actuellement. Vous pourriez envisager d’écrire votre propre méthode d’extension (comme celle de la bibliothèque d’Omer mais utilisant IQueryable au lieu de IEnumerable pour prendre en charge l’exécution côté serveur).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top