J'utilise ADO.NET Entity Framework pour gérer une hiérarchie d'objets. Chacun a un seul parent et zéro ou plusieurs enfants.Pourquoi mon code Linq to Entities duplique-t-il des lignes?
Je vous présente ces derniers dans mon application WPF avec un contrôle TreeView. De nouvelles choses peuvent être ajoutés aux enfants sélectionnés choses avec le clic d'un bouton ...
Visual Basic ...
Private Sub ButtonAddThing_Click(...) Handles ButtonAddThing.Click Dim NewThing As New Thing NewThing.Id = Guid.NewGuid() NewThing.Parent = DirectCast(TreeViewThings.SelectedItem, Thing) ... db.AddToThing(NewThing) db.SaveChanges() TreeViewThings.UpdateLayout() End Sub
Mais, il y a un problème. Plutôt que d'ajouter simplement une nouvelle chose à la base de données, c'est d'abord en ajoutant une copie du parent, mais bizarrement avec un identifiant unique vide pour un identifiant.
Ceci encombre la base de données et déclenche l'exception suivante après le deuxième clic sur le bouton ButtonAddThing.
Exception: "Violation de l'enseignement primaire KEY contrainte 'PK_Thing' Impossible d'insérer clé en double dans l'objet 'dbo.Thing' L'instruction a été interrompue.".
Ce sont les instructions d'insertion T-SQL généré ...
La duplication mère:
exec sp_executesql N'insert [dbo].[Thing]([Id], [ParentId], ...) values (@0, @1, ...) ',N'@0 uniqueidentifier,@1 uniqueidentifier,...', @0='00000000-0000-0000-0000-000000000000', @1='389D987D-79B1-4A9D-970F-CE15F5E3E18A', ...
La nouvelle chose:
exec sp_executesql N'insert [dbo].[Thing]([Id], [ParentId], ...) values (@0, @1, ...) ',N'@0 uniqueidentifier,@1 uniqueidentifier,...', @0='88641EBB-B7D7-4203-8191-B27E1D1E1840', @1='391FF0D9-40ED-4349-BB91-0F2E440EF8C9', ...
Pourquoi mon LINQ to Entities code dupliquer ces lignes parent? Comment puis-je gérer correctement cette relation parent/enfant?
Mise à jour: Ce n'est pas seulement un problème lors de la création de nouvelles choses. Mon bouton "supprimer" ne fonctionne pas correctement non plus.
Private Sub ButtonDeleteThing_Click(...) db.DeleteObject(DirectCast(TreeViewThings.SelectedItem, Thing)) db.SaveChanges() End Sub
ni
Private Sub ButtonDeleteThing_Click(...) Dim Id As Guid = DirectCast(TreeViewThings.SelectedItem, Thing).Id Dim DoomedThing As Thing = (From t In db.Thing _ Where t.Id = Id _ Select t).First db.DeleteObject(DoomedThing) db.SaveChanges() End Sub
Je suis suivi le profileur SQL Server pendant que je déboguer mon application. Comportement observé:
- Le premier clic sur le bouton supprime très bien.
- Le deuxième clic sur un bouton insère un parent dupliqué (clé primaire GUID uniqueidentifier vide), puis effectue la suppression.
- Le troisième clic sur le bouton échoue (violation de la contrainte PRIMARY KEY) car il ne peut pas insérer une seconde chose avec une clé primaire GUID vide.
C'était le coup de pouce dans la bonne direction dont j'avais besoin. Merci.Il génère une requête de sélection supplémentaire maintenant, mais seulement l'insertion. –
Pas de problème. Si ParentId est un champ dans votre table, vous devriez être en mesure de le faire: Dim ParentId Comme Guid = DirectCast (TreeViewThings.SelectedItem, chose) .id Thing.ParentId = ParentId db.SaveChanges() TreeViewThings.UpdateLayout ( Non? Cela vous sauverait le select. – achinda99
J'ai perdu tout le formatage que j'avais, mais je suis sûr que vous pouvez comprendre ce que j'essayais de dire. Je n'ai jamais compris pourquoi dans VB, la syntaxe utilisait une nouvelle ligne pour déterminer la fin de l'instruction et pas un autre caractère (comme ";" en C#) – achinda99