Wpf ADO.NET实体框架:相关对象的更新问题

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正确显示了所有演员,并且

我正在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函数:

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"/>