Мне нужна помощь в понимании ADO.NET Entity Framework.
Я пытаюсь представить и управлять иерархическими данными в элементе управления WPF TreeView с помощью ADO.NET Entity Framework.
http://img14.imageshack.us/img14/7158/thingpi1.gif
У каждой из этих вещей есть единственный родитель и ноль или более детей.
Моя кнопка "удалить" ...
Private Sub ButtonDeleteThing_Click(...)
db.DeleteObject(DirectCast(TreeViewThings.SelectedItem, Thing))
db.SaveChanges()
End Sub
Я наблюдаю за профилировщиком SQL Server, пока отлаживаю свое приложение:
- Первое нажатие кнопки удаляет просто отлично.
- При нажатии второй кнопки выполняется вставка повторяющегося родителя (но с пустым первичным ключом GUID uniqueidentifier), а затем выполняется удаление.
- При третьем нажатии кнопки происходит сбой (нарушение ограничения PRIMARY KEY), поскольку невозможно вставить другую строку с пустым первичным ключом GUID.
Неожиданное, сгенерированное дублирование 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', ...
Но это не просто удаление. Моя кнопка «добавить» ведет себя аналогичным образом с неожиданными вставками. Он следует той же схеме.
Это заставляет меня думать, что существует более фундаментальная проблема, связанная с тем, как я привязываю эти классы сущностей к WPF TreeView или к самой моей модели данных.
Вот соответствующий код ...
XAML ...
<TreeView Name="TreeViewThings"
ItemsSource="{Binding}"
TreeViewItem.Expanded="TreeViewThings_Expanded"
TreeViewItem.Selected="TreeViewThings_Selected"
... >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Thing}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Title}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
<Button Name="ButtonAddThing" Content="Add Thing" ... />
<Button Name="ButtonDeleteThing" Content="Delete Thing" ... />
Visual Basic...
Partial Public Class Window1
Dim db As New ThingProjectEntities
Private Sub Window1_Loaded(...) Handles MyBase.Loaded
TreeViewThings.ItemsSource = _
From t In db.Thing.Include("Children") _
Where (t.Parent Is Nothing) _
Select t
End Sub
Private Sub TreeViewThings_Expanded(...)
Dim ExpandedTreeViewItem As TreeViewItem = _
DirectCast(e.OriginalSource, TreeViewItem)
LoadTreeViewChildren(ExpandedTreeViewItem)
End Sub
Sub LoadTreeViewChildren(ByRef Parent As TreeViewItem)
Dim ParentId As Guid = DirectCast(Parent.DataContext, Thing).Id
Dim ChildThings As System.Linq.IQueryable(Of Thing)
ChildThings = From t In db.Thing.Include("Children") _
Where t.Parent.Id = ParentId _
Select t
Parent.ItemsSource = ChildThings
End Sub
Private Sub ButtonAddThing_Click(...)
Dim NewThing As New Thing
NewThing.Id = Guid.NewGuid()
Dim ParentId As Guid = _
DirectCast(TreeViewThings.SelectedItem, Thing).Id
NewThing.Parent = (From t In db.Thing _
Where t.Id = ParentId _
Select t).First
...
db.AddToThing(NewThing)
db.SaveChanges()
TreeViewThings.UpdateLayout()
End Sub
Private Sub ButtonDeleteThing_Click(...)
db.DeleteObject(DirectCast(TreeViewThings.SelectedItem, Thing))
db.SaveChanges()
End Sub
...
End Class
Что я делаю неправильно? Почему он генерирует эти странные вставки?
Обновлять:
Я совершил прорыв. Но я все еще не могу этого объяснить.
Я избавился от причины, когда упростил свой код для этого вопроса.
Вместо использования Linq, например:
From t In db.Thing.Include("Children") Where ...
Я использовал Linq, например:
From t In db.Thing.Include("Children").Include("Brand") Where ...
Видите ли, сущность My Thing связана с другой сущностью Бренда.
http://img25.imageshack.us/img25/3268/thingbrandct4.gif
Я подумал, что это не имеет отношения к делу, поэтому не включил его в вопрос выше.
По-видимому, это было причиной моих неожиданных проблемных вставок в мою таблицу Thing.
Но почему? Кто-нибудь может объяснить, почему это происходило? Я бы хотел лучше это понять.