2009-02-13 6 views
0

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?

ADO.NET Entity Framework Object with parent and children http://img14.imageshack.us/img14/7158/thingpi1.gif

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é:

  1. Le premier clic sur le bouton supprime très bien.
  2. Le deuxième clic sur un bouton insère un parent dupliqué (clé primaire GUID uniqueidentifier vide), puis effectue la suppression.
  3. 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.

Répondre

2

Vous devriez être en mesure de faire quelque chose comme ceci:

 
Dim ParentId As Guid = DirectCast(TreeViewThings.SelectedItem, Thing).Id 
NewThing.Parent = (From t In db.Thing _ 
        Where t.Id = ParentId _ 
        Select t).First 

qui va construire le modèle hiérarchique que vous allez pour.

+0

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. –

+0

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

+0

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

Questions connexes