Почему мой код Linq to Entities дублирует строки? - PullRequest
0 голосов
/ 13 февраля 2009

Я использую ADO.NET Entity Framework для управления иерархией объектов. У каждого есть один родитель и ноль или более детей.

Объект ADO.NET Entity Framework с родителями и дочерними элементами http://img14.imageshack.us/img14/7158/thingpi1.gif

Я представляю их в своем приложении WPF с элементом управления TreeView. Новые вещи могут быть добавлены в качестве дочерних к выбранным вещам одним нажатием кнопки ...

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

Но есть проблема. Вместо простого добавления нового Thing в базу данных, он также сначала добавляет дубликат родителя, но странно с пустым уникальным идентификатором для идентификатора.

Это загромождает базу данных и выдает следующее исключение после второго нажатия кнопки ButtonAddThing.

Исключение: "Нарушение ПЕРВИЧНОГО КЛЮЧА" ограничение "PK_Thing". Не могу вставить дубликат ключа в объекте 'dbo.Thing'. Заявление было прекращено. "

Это сгенерированные операторы вставки T-SQL ...

Дублирование родительского элемента:

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',
...

Новая вещь:

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',
...

Почему мой код Linq to Entities дублирует эти родительские строки? Как я могу правильно справиться с этими отношениями родитель / ребенок?


Обновление: это не просто проблема при создании новых вещей. Моя кнопка «Удалить» также не работает должным образом.

Private Sub ButtonDeleteThing_Click(...)
    db.DeleteObject(DirectCast(TreeViewThings.SelectedItem, Thing))
    db.SaveChanges()
End Sub

ни

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

Я наблюдаю за профилировщиком SQL Server во время отладки приложения. Наблюдаемое поведение:

  1. Первое нажатие кнопки удаляет просто отлично.
  2. Вторым нажатием кнопки вставляется родительский элемент с дубликатом (пустой первичный ключ уникального идентификатора GUID), а затем выполняется удаление.
  3. Сбой третьего нажатия кнопки (нарушение ограничения PRIMARY KEY), поскольку он не может вставить вторую вещь с пустым первичным ключом GUID.

1 Ответ

2 голосов
/ 13 февраля 2009

Вы должны быть в состоянии сделать что-то вроде этого:

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

Это создаст иерархическую модель, к которой вы стремитесь.

...