Мне нужна помощь в понимании 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.
Но почему? Кто-нибудь может объяснить, почему это происходило? Я бы хотел лучше это понять.