entity framework – Addition/removal of entities in EF6 many-to-many architecture


Is there a way to do this many-to-many update with less code? It feels awfully bulky to me.

I started out using AutoMapper to avoid the explicit value assignments, but then the mapped Movie doesn’t come with its Genre entities. I had to scrap that so I could use the Include() extension method to accomplish the goal. But even that, if it worked, wouldn’t trim all of this down by much.

The idea is to update the database with the movie genres specified by the user, both addition and removal.

If this is the most compact it can get, so be it. But I thought I’d at least check first.

Controller

<HttpPost>
<ValidateAntiForgeryToken>
Public Function Edit(ViewModel As MovieViewModel) As ActionResult
  Dim oUnchecked As Func(Of GenreCheckBox, Boolean)
  Dim oChecked As Func(Of GenreCheckBox, Boolean)
  Dim oMovie As Db.Movie
  Dim oGenre As Db.Genre

  If Me.ModelState.IsValid Then
    Using oDb As Db.Context = Db.Context.Create
      oMovie = oDb.Movies.Include(Function(Movie) Movie.Genres).SingleOrDefault(Function(Movie) Movie.Id = ViewModel.Id)

      If oMovie Is Nothing Then
        Edit = Me.HttpNotFound
      Else
        oUnchecked = Function(CheckBox) CheckBox.IsChecked = False
        oChecked = Function(CheckBox) CheckBox.IsChecked = True

        oMovie.ReleaseYear = ViewModel.ReleaseYear
        oMovie.Rating = ViewModel.Rating
        oMovie.Price = ViewModel.Price
        oMovie.Title = ViewModel.Title

        ViewModel.GenreCheckBox.Where(oUnchecked).ForEach(Sub(CheckBox)
                                                            oGenre = oDb.Genres.Single(Function(Genre) Genre.Id = CheckBox.Id)
                                                            oMovie.Genres.Remove(oGenre)
                                                          End Sub)

        ViewModel.GenreCheckBox.Where(oChecked).ForEach(Sub(CheckBox)
                                                          oGenre = oDb.Genres.Single(Function(Genre) Genre.Id = CheckBox.Id)
                                                          oMovie.Genres.Add(oGenre)
                                                        End Sub)

        oDb.SaveChanges()
      End If
    End Using

    Edit = Me.RedirectToAction(NameOf(MoviesController.Index))
  Else
    Edit = Me.View(ViewModel)
  End If
End Function

Movie

Public Class Movie
  Public Property Id As Integer
  Public Property ReleaseYear As Integer
  Public Property Rating As String
  Public Property Price As Decimal
  Public Property Title As String
  Public Property Genres As ICollection(Of Genre) = New List(Of Genre)
End Class

Genre

Public Class Genre
  Public Property Id As Integer
  Public Property Name As String
  Public Property Movies As ICollection(Of Movie) = New List(Of Movie)
End Class