MVC4 controller with Many to Many relationship

前端 未结 3 1979
你的背包
你的背包 2021-01-15 05:35

I have the two entities, Arena and Regulator, which have a many to many relationship between them. I have implemented what seems to be the EF code first accepted solution (

3条回答
  •  春和景丽
    2021-01-15 06:41

    After a lot of research I have understood that EF cannot update relationships - very surprising and disappointing. Aparently, the suggested solution is a manual update of the join table and navigation properties - not very good. NHibernate apparently does do this out of the box and I fully intend to investigate next time I need this.

    Luckily I came across a truly great solution from Refactor(This) that adds an extension method to DbContext, allowing automated updating of complex relationships. There is even a Nuget package!

    So here is my full solution:

    I've added an integer list to the Regulator class, which gets the IDs of the selected Arenas.

    Public Class Regulator
        Public Property Id As Integer
        Public Property Name As String
        Public Property ArenaIDs() As ICollection(Of Integer)
        Public Overridable Property Arenas() As ICollection(Of Arena)
    End Class
    

    In the GET Edit action, this is taken care of and a MultiSelectList is created:

    ' GET: /Regulator/Edit/5
    
    Function Edit(Optional ByVal id As Integer = Nothing) As ActionResult
        Dim regulator As Regulator = db.Regulators.Find(id)
        If IsNothing(regulator) Then
            Return HttpNotFound()
        End If
        For Each a In regulator.Arenas
            regulator.ArenaIDs.Add(a.Id)
        Next
        ViewBag.MultiSelectArenas = New MultiSelectList(db.Arenas.ToList(), "Id", "Name", regulator.ArenaIDs)
        Return View(regulator)
    End Function
    

    And the MultiSelectList is used in the View:

        
    @Html.ListBoxFor(Function(m) m.ArenaIDs, ViewBag.MultiSelectArenas) @Html.ValidationMessageFor(Function(model) model.Arenas)

    In the POST Edit action the selection IDs are retrieved and used to update the Arenas collection. Then the magic comes in the with the UpdateGraph extension method that does what EF can not and updates the relationship!

    ' POST: /Regulator/Edit/5
    
     _
     _
    Function Edit(ByVal regulator As Regulator) As ActionResult
        If ModelState.IsValid Then
            For Each i In regulator.ArenaIDs
                regulator.Arenas.Add(db.Arenas.Find(i))
            Next
    
            db.UpdateGraph(Of Regulator)(regulator, Function(map) map.AssociatedCollection(Function(r) r.Arenas))
    
            db.SaveChanges()
            Return RedirectToAction("Index")
        End If
    

提交回复
热议问题