使用MVC 3,EF 4.1,DbContext和AutoMapper保存嵌套集合

时间:2011-04-29 17:17:25

标签: asp.net-mvc vb.net entity-framework-4.1 automapper

我很难获得嵌套集合(在我的情况下为Tags),在传递到我的控制器后提交回数据库。我使用EF 4.1与DbContext API,MVC 3和Automapper。

我的模特:

Partial Public Class Proposal
    Public Property Id As Integer
    Public Property Memo As String
    Public Property EntryDate As Nullable(Of Date)
    Public Overridable Property CategoryTags As ICollection(Of CategoryTag) = New HashSet(Of CategoryTag)

End Class

Public Class ProposalViewModel

    Public Property Id As Integer
    <DataType(DataType.MultilineText)>
    Public Property Memo As String
    <DisplayFormat(ApplyFormatInEditMode:=True, DataFormatString:="{0:d}")>
    Public Property EntryDate As Nullable(Of Date)
    Public Overridable Property CategoryTags As ICollection(Of CategoryTag) = New HashSet(Of CategoryTag)
End Class

我的观点使用以下帖子中的代码添加标记:http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3。基本上,标签是通过添加INPUT元素创建的,其名称属性设置为“CategoryTag [0] .Id”,“CategoryTag [1] .Id”等......这些输入的值是我数据库中标签的有效ID

最后,我的POST代码:

<HttpPost()>
Public Function Edit(ByVal pvm As ProposalViewModel) As ActionResult

    Dim p As New Proposal

    p = AutoMapper.Mapper.Map(Of ProposalViewModel, Proposal)(pvm)

    If (ModelState.IsValid) Then
        db.Entry(p).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    Else
        Return View(pvm)
    End If

End Function

pvm对象返回到我的控制器,其值设置为我希望它们。如果我在运行时添加两个标记,那么它的集合中有两个带有适当ID的CategoryTag对象。问题是,在我调用SaveChanges时,相应的记录不会在我的多对多关系表中创建(在本例中为ProposalCategoryTag)。

知道我做错了吗?

更新:

我没有发现任何相关内容,并且已经像下面那样手动操作。我不喜欢这种方法,但它有效。

<HttpPost()>
Public Function Edit(ByVal pvm As ProposalViewModel) As ActionResult

    Dim p As New Proposal
    Dim tempTag As CategoryTag

    p = AutoMapper.Mapper.Map(Of ProposalViewModel, Proposal)(pvm)

    If (ModelState.IsValid) Then

        db.Proposals.Attach(p)
        db.Entry(p).Collection("CategoryTags").Load()

        For Each ct As CategoryTag In pvm.Tags

            tempTag = db.CategoryTags.Find(ct.Id)

            If tempTag Is Nothing Then
                Continue For
            End If

            If p.CategoryTags.Contains(tempTag) Then
                Continue For
            End If

            p.CategoryTags.Add(tempTag)
        Next

        db.Entry(p).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    Else

        Return View(pvm)

    End If

End Function

1 个答案:

答案 0 :(得分:0)

更新:

我没有发现任何相关内容,并且已经像下面那样手动操作。我不喜欢这种方法,但它有效。

    <HttpPost()>
    Public Function Edit(ByVal pvm As ProposalViewModel) As ActionResult

        Dim p As New Proposal
        Dim tempTag As CategoryTag

        p = AutoMapper.Mapper.Map(Of ProposalViewModel, Proposal)(pvm)

        If (ModelState.IsValid) Then

            db.Proposals.Attach(p)
            db.Entry(p).Collection("CategoryTags").Load()

            For Each ct As CategoryTag In pvm.Tags

                tempTag = db.CategoryTags.Find(ct.Id)

                If tempTag Is Nothing Then
                    Continue For
                End If

                If p.CategoryTags.Contains(tempTag) Then
                    Continue For
                End If

                p.CategoryTags.Add(tempTag)
            Next

            db.Entry(p).State = EntityState.Modified
            db.SaveChanges()
            Return RedirectToAction("Index")
        Else


            Return View(pvm)

        End If

    End Function