Wpf ADO.NET实体框架:相关对象的更新问题
我正在SQL Express DB上玩一个带有WPf/MVVM和ADO.NET EF的小VB.NET应用程序,在尝试更新相关对象时遇到了问题: 我的数据库有三个表“tb_Actors”、“tb_Movies”和一个连接表“tb_Movies\u Actors”。EF设计器创建两个实体“演员”和“电影”,并根据外键正确设置其导航属性。因此,我们能够提出一个视图,该视图绑定到一个viewModels属性,该属性包含所有“Movies.Actors” 我视图中的DataGrid正确显示了所有演员,并且——如果它是一个新演员,但我的DB中还没有——我可以向电影中添加新演员,并正确地将更改保存到DB中 但是,如果我想向已经在DB中的电影添加演员,我将在tb_actors表中获得一个双条目。首先,我将主键字段(name和id)设置为UNIQUE,但随后代码中断。然后,我添加了一个小的更新例程,用于检查电影中的每个相关演员是否是已知演员,并将“新演员”id更改为“旧演员”id–这也会中断 有没有办法告诉EF,它必须确定添加的相关对象(=添加到电影中的已知演员)是否已经在DB中,因此它必须只向连接表插入一个新条目,而不向相关对象表插入一个新条目 我的下一步将是分离相关对象,并在我自己的数据访问代码中执行所有更新/插入…但由于我相信我的问题是围绕一个典型的EF用例,因此必须有一种更优雅的方式来处理相关对象的更新 非常感谢您的任何想法、答案和提示 *编辑以下是相关的代码片段* 1) 我的MovieRepository数据访问类中有以下LoadMovies函数:Wpf ADO.NET实体框架:相关对象的更新问题,wpf,entity-framework,ado.net,mvvm,Wpf,Entity Framework,Ado.net,Mvvm,我正在SQL Express DB上玩一个带有WPf/MVVM和ADO.NET EF的小VB.NET应用程序,在尝试更新相关对象时遇到了问题: 我的数据库有三个表“tb_Actors”、“tb_Movies”和一个连接表“tb_Movies\u Actors”。EF设计器创建两个实体“演员”和“电影”,并根据外键正确设置其导航属性。因此,我们能够提出一个视图,该视图绑定到一个viewModels属性,该属性包含所有“Movies.Actors” 我视图中的DataGrid正确显示了所有演员,并且
Private Function LoadMovies() As List(Of Movies)
movs = From m In dc.Movies.Include("Actors") Select m
Return movs.ToList
End Function
2) my viewModel的以下属性公开与特定电影相关的演员:
Public ReadOnly Property actors() As ICollectionView
Get
If evs Is Nothing Then
evs = New CollectionViewSource
evs.Source = _movie.Actors
End If
Return evs.View
End Get
End Property
3) 在我的MovieDetail视图中,我将datagrid绑定到属性:
<DataGrid Name="ActTestGrid" HorizontalAlignment="Left" VerticalAlignment="Stretch" ItemsSource="{Binding actors}" AutoGenerateColumns="False" Width="150" Height="120" Style="{StaticResource dgTemplate}" RowStyle="{StaticResource dgRowTemplate}" CellStyle="{StaticResource dgCellTemplate}" CanUserSortColumns="True" CanUserAddRows="True" CanUserDeleteRows="True" HeadersVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=name, UpdateSourceTrigger=PropertyChanged}" CanUserSort="true"/>
</DataGrid.Columns>
</DataGrid>
EF做它所做的,你不能告诉它再做了,也就是说它不会验证你的数据。EF将插入您告诉它插入(或尝试插入)的内容。在调用“保存更改”之前,数据验证是您的责任
为了解决这个问题,考虑在视图中提供一个带有演员名字列表的组合框。组合框的
IsEditable
设置为true,文本属性在ViewModel中以字符串形式绑定到ActorName
。如果用户选择现有的参与者,EF将不会尝试插入新的参与者。如果用户键入新名称,EF将创建一个新的参与者
以下是一些使用品牌名称的代码:
Public Property BrandName() As String
Get
Return _brandName
End Get
Set
_brandName = value.Trim()
If _brandName <> String.Empty Then
Dim b As Brand = _brands.ToList().Find(Function(br) br.BrandName.ToUpper() = _brandName.ToUpper())
If b Is Nothing Then
Brand = New Brand()
Brand.BrandName = _brandName
Else
Brand = b
End If
Else
Brand = Nothing
End If
CheckIsDirty()
RaisePropertyChanged("BrandName")
End Set
End Property
Public Property BrandName()作为字符串
收到
Return\u brandName
结束
设置
_brandName=value.Trim()
如果_brandName字符串为空,则
Dim b As Brand=\u brands.ToList().Find(函数(br)br.BrandName.ToUpper()=\u BrandName.ToUpper())
如果b什么都不是
品牌=新品牌()
Brand.BrandName=\u BrandName
其他的
品牌=b
如果结束
其他的
品牌=无
如果结束
CheckIsDirty()
RaisePropertyChanged(“品牌名称”)
端集
端属性
在这方面:
<ComboBox Grid.Row="1" Grid.Column="0" Height="28" HorizontalAlignment="Stretch" Margin="110,0,28,0" VerticalAlignment="Top" TabIndex="1" ItemsSource="{Binding Brands}" DisplayMemberPath="BrandName" Text="{Binding BrandName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True"/>
如果需要帮助修复代码,您需要显示代码。
<ComboBox Grid.Row="1" Grid.Column="0" Height="28" HorizontalAlignment="Stretch" Margin="110,0,28,0" VerticalAlignment="Top" TabIndex="1" ItemsSource="{Binding Brands}" DisplayMemberPath="BrandName" Text="{Binding BrandName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True"/>