Une table -> deux entity types sans colonne discriminante en base, gestion des relations
Avec mes deux précédents posts (ssdl view et TPT et ssdl view et TPH), je vous ai montré comment passer d'une table Employees à deux entity types : Employee et Manager avec Manager qui hérite de Employee.
Maintenant, allons un peu plus loin. Dans ma table, j'ai une FK entre Employees.EmployeeManager et Employees.EmployeeId.
Dans mon modèle, je me retrouve donc avec une relation entre Employee et Employee comme en base.
Le problème c'est que ce que je voudrais, c'est une relation entre Manager et Employee.
Pour cela, il faut que je commence par supprimer la relation du CSDL puis la relation du SSDL (possible uniquement en modifiant le xml de l'edmx à la main). Dans le cas contraire, j'aurai une erreur dans mon EDM. Dans l'hypothèse où on supprime la relation CSDL directement dans le xml, il faut alors la supprimer également dans la partie MSL. Avec le designer, cela est fait automatiquement.
Ensuite, je rajoute une relation entre Manager et Employee que je mappe sur la table Employees.
Cool ça marche !
Maintenant, allons plus loin, comment faire passer un employé au poste de manager ? Autrement dit, comment rajouter des sous-employés à un employé ?
Voici un petit bout de code qui permet de faire ça :
var manager = new Manager { EmployeeId = oldEmployee.EmployeeId, EmployeeManager = oldEmployee.EmployeeManager, EmployeeName = oldEmployee.EmployeeName };
ObjectStateEntry ose;
context.ObjectStateManager.TryGetObjectStateEntry(manager, out ose);
if (ose == null)
context.AddToEmployeesWithManager(manager);
context.Detach(oldEmployee);
context.AcceptAllChanges();
manager.SubEmployees.Add(new Employee { EmployeeId = newEmployeeId, EmployeeName = newEmployeeName });
context.SaveChanges();
Et voilà, le tour est joué !
Maintenant apportons quelques explications à ce code.
Quand on affecte l'EmployeeManager à manager, cela a pour effet de rajouter l'entité manager au contexte de oldEmployee.
Cependant, dans le cas où le contexte de oldEmployee ne serait pas notre instance context ou dans le case où EmployeeManager serait null, il va falloir ajouter notre nouveau manager à notre instance context.
D'où le test avec TryGetObjectStateEntry.
Une fois cela fait, il faut détacher oldEmployee afin de ne pas avoir de conflit.
Maintenant qu'on a une instance de manager, on va pouvoir rajouter des sous-employés. Cependant, côté base, nous n'avons rien changé (le record sera le même) mais si on fait un SaveChanges, on va avoir un problème car l'instance de manager est marquée comme Added. Il faut donc lui dire que rien n'a été modifié, d'où le AcceptAllChanges.
Ensuite, on rajoute notre(nos) nouveau(x) employé(s). Il ne reste alors plus qu'à persister le contexte en base.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :