Hi experts,
I’m playing around with a little VB.NET app with WPf/MVVM and ADO.NET EF on a SQL Express-DB and I’m running into problems while trying to update related objects:
My DB has three tables “tb_Actors”, “tb_Movies” and a junction table “tb_movies_actors”. The EF designer creates two entities "Actors" und "Movies" and sets their navigation properties based on the foreign keys correctly. So was able to come up with a view which binds to a viewModels property which has all “Movies.Actors”.
The DataGrid in my view displays all actors correctly, and – if it’s a new actor which isn’t in my DB already- I am able to add new actors to a movie and persist the changes to the DB correctly.
However, if I want to add an actor to a movie who is already in my DB, I’ll get a double entry in my tb_actors table. First I’ve set the primary key fields (name and id) to UNIQUE, but then my code breaks. Then, I’ve added a little update routine which checks for each related actor of a movie if it’s a known actor, and changes the “new actors” id to the “old actors” id – this also breaks.
Is there a way to tell EF that it has to determine if an added related object (= already known actor added to movie) is already in the DB, and it therefore has to insert only a new entry to to junction table, but not to the related objects table?
My next step would be detaching the related objects and do all updates/inserts in my own data access code … but since I believe my problem is around a typical EF use case, there must be a more elegant way to deal with updates on related objects.
Any thoughts, answers, hints are highly appreciated!
* EDIT Here are the relevant code snippets *
1) I have the following LoadMovies Function in my MovieRepository data access class:
Private Function LoadMovies() As List(Of Movies)
movs = From m In dc.Movies.Include("Actors") Select m
Return movs.ToList
End Function
2) The following property of my viewModel exposes the actors related to a specific movie:
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) In my MovieDetail view, I've a datagrid binding to the property:
<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) This is my updateMovie Function of my MovieRepository (as by now):
Public Sub UpdateMovie(ByVal movie As Movies)
If movie Is Nothing Then
Throw New ArgumentNullException("Movie")
Else
dc.SaveChanges()
End If
End Sub