Joindre à l'aide de LINQ to SQL

Je construis une application WPF en utilisant Visual Studio 2015 contre Entity Framework 6 et SQL Server 2008. J'ai ces deux tables:

Employee ----------------------------- EmployeeId FirstName LastName ... other columns EmployeeStatus ----------------------------- EmployeeStatusId EmployeeId (Foreign Key to Employee.EmployeeId) ValidEmployeeStatusId 

L'application doit récupérer tous les employés dont EmployeeStatus.ValidEmployeeStatusId n'est pas 2 et non 4 (Inactif et Absence). J'ai écrit cette requête LINQ, mais elle s'exécute pour toujours et ne renvoie jamais aucun résultat:

 var query = (from e in context.Employees from es in context.EmployeeStatus .Where(x => e.employeeID == x.employeeID && (x.validEmployeeStatusID != 2 && x.validEmployeeStatusID != 4) .DefaultIfEmpty() select new EmployeeViewModel { EmployeeId = e.employeeID, /* set other properties*/ }); return await Task.Run(() => new ObservableCollection<EmployeeViewModel>(query)); 

Qu'est-ce que je fais mal?

Mise à jour : J'ai découvert ce qui me tue sur la lenteur … Chaque EmployeeViewModel appelait la database dans son ctor pour peupler certaines ObservableCollections. Transformé ces propriétés en static et ajouté un static bool ; si c'est faux, remplissez les propriétés et définissez bool sur true. Toutes les instances utilisent donc les mêmes données pour les propriétés qui appelaient la database. Pour ~ 4000 loggings, c'était beaucoup d'appels.

Vous pouvez get le résultat souhaité avec une jointure à gauche.

 var query = (from e in context.Employees join es in context.EmployeeStatus on e.employeeID equals es.employeeID into empStatuses from emps in empStatuses.DefaultIfEmpty() where emps.validEmployeeStatusID != 2 && emps.validEmployeeStatusID != 4 select new EmployeeViewModel { EmployeeId = e.employeeID, /* set other properties*/ }); 

Je pense que vous n'avez pas besoin d'effectuer une join

Essayez cette requête

 var query = (from e in context.Employees where e.EmployeeStatus.validEmployeeStatusID != 2 && e.EmployeeStatus.validEmployeeStatusID != 4 select new EmployeeViewModel { EmployeeId = e.employeeID, /* set other properties*/ }); 

Vous pouvez essayer !Any requête LINQ basée qui devrait être traduite en requête SQL NOT EXISTS , qui est une bonne alternative à une jointure de nos jours. De plus, il évite la duplication d'loggings d'employés qui se produit lors de l'utilisation de jointures.

 var query = (from e in context.Employees where !context.EmployeeStatus.Any(s => e.employeeID == s.employeeID && (s.validEmployeeStatusID == 2 || s.validEmployeeStatusID == 4)) select new EmployeeViewModel { EmployeeId = e.employeeID, /* set other properties*/ }); 

Vous pouvez également essayer la version de jointure suivante (en fait antijoin ) de la requête:

 var query = (from e in context.Employees join s in context.EmployeeStatus .Where(x => x.validEmployeeStatusID == 2 || x.validEmployeeStatusID == 4)) on e.employeeID equals s.employeeID into statusGroup from s in statusGroup.DefaultIfEmpty() where s == null select new EmployeeViewModel { EmployeeId = e.employeeID, /* set other properties*/ });