2010-08-24 90 views
0

我在一個SQL Express-DB上玩WPF/MVVM和ADO.NET EF的小VB.NET應用程序,我遇到了問題試圖更新相關對象:ADO.NET實體框架:有關對象更新的問題

我的數據庫有三個表「tb_Actors」,「tb_Movies」和一個聯結表「tb_movies_actors」。 EF設計人員創建兩個實體「Actors」和「Movies」,並根據外鍵正確設置其導航屬性。所以能夠提出一個視圖,該視圖綁定到具有所有「Movies.Actors」的viewModels屬性。

我的視圖中的DataGrid正確顯示所有actor,並且 - 如果它是一個新的actor,它不在我的數據庫中,我可以將新actor添加到電影中,並將更改持久保存到數據庫中。

但是,如果我想將演員添加到已經在我的數據庫中的電影中,我會在我的tb_actors表中獲得一個雙重條目。首先,我將主鍵字段(名稱和ID)設置爲UNIQUE,但隨後我的代碼被中斷。然後,我添加了一個小更新例程,該例程檢查電影的每個相關演員是否是已知演員,並將「新演員」ID更改爲「老演員」ID - 這也會中斷。

有沒有辦法告訴EF它必須確定添加的相關對象(=已知的actor是否已添加到影片中)已經在數據庫中,因此它只需要向聯結表中插入一個新條目,但不是相關的對象表?

我的下一步將是分離相關對象,並在我自己的數據訪問代碼中執行所有更新/插入操作......但由於我相信我的問題是圍繞着一個典型的EF用例,因此必須有一個更優雅的方式來處理更新相關對象。

任何想法,答案,提示都非常感謝!

*編輯下面是相關的代碼片段*

1)我有以下LoadMovies功能在我MovieRepository數據訪問類:

Private Function LoadMovies() As List(Of Movies) 
     movs = From m In dc.Movies.Include("Actors") Select m 
     Return movs.ToList 
End Function 

2)我的視圖模型暴露了以下屬性演員相關的具體電影:

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

4)這是我的MovieRepository我updateMovie功能(如現在):

Public Sub UpdateMovie(ByVal movie As Movies) 
     If movie Is Nothing Then 
      Throw New ArgumentNullException("Movie") 
     Else 

      dc.SaveChanges() 
     End If 
End Sub 
+0

你需要證明你的代碼,如果您想知道如何修復它。 – 2010-08-24 12:06:24

回答

0

EF做它做什麼,你不能告訴它做了,那就是它不會驗證你的數據。 EF會插入你告訴它插入(或嘗試)的內容。在您調用保存更改之前,數據驗證是您的責任。

爲了解決這個問題,考慮在視圖中提供一個組合框和演員姓名列表。組合框的IsEditable設置爲true,文本屬性綁定到您的ViewModel中的ActorName AS String。如果用戶選擇現有的演員,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 

並且在這個視圖:

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