具有实体框架的活动记录

时间:2012-05-14 21:23:37

标签: vb.net entity-framework activerecord entity-framework-4 ef-code-first

我正在开发一个使用ADO.NET(原始sql)和Active Record模式构建的项目。我正在慢慢地将它从ADO.NET转移到Entity Framework Code First 4.3。

这是模式的一个例子。接口是静态Load和实例Save(和Delete - 未显示)。

Public Class Part
    Public Property Id as Integer

    Public Shared Function Load(_id As Integer) As Part
        Using context As New DataContext()
            Return context.Find(_id)
        End Using
    End Function

    Public Sub Save()
        Using context As New DataContext()
            If Id = 0 Then
                context.Parts.Add(Me)
            Else
                context.Entry(Me).State = Data.EntityState.Modified
            End If

            context.SaveChanges()
        End Using
    End Sub
End Class

我意识到Active Record并不适合EF,但我希望能够在不触及其余代码的情况下删除所有ADO.NET代码。

这大部分都有效,但我遇到了一个我不知道如何解决的问题。为了使外键保持同步,我们可以像这样处理它:

Public Sub Save()
    ParentPart = Part.Load(ParentPartId)
    ChildPart = Part.Load(ChildPartId)

    Using context = New iTracContext()

        If bid = 0 Then
            context.BillOfMaterials.Add(Me)
        Else
            context.Entry(Me).State = Data.EntityState.Modified
        End If

        context.SaveChanges()
    End Using
End Sub

这可以确保EF不会抱怨我们有不匹配的关系--Id也会赢。

问题在于,当我保存时,它会抛出异常。

  

ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

这是从以下行引出的:

context.Entry(Me).State = Data.EntityState.Modified

此上下文中ObjectStateManager的内容如何?它是全新的,应该是空的,不是吗?

如果我删除了两条Part.Load(...)行,则可以正常工作。

是否有某种类型的更改跟踪器存在于我不知道的上下文之外?这似乎会杀死任何积极记录模式的尝试。

我也对如何使Active Record使用EF的任何建议持开放态度。 context.Entry行是可怕的,但我不知道还能做什么。

告诉我不要做Active Record没有帮助,但请随意。

1 个答案:

答案 0 :(得分:0)

我相信实体框架可能仍在从您加载它的上下文中跟踪对象,因为您为每个加载和保存调用创建了新的上下文。如果是这种情况,请在加载后尝试分离对象:

Public Shared Function Load(_id As Integer) As Part
    Using context As New DataContext()
        Part part = context.Find(_id)
        context.Entry(part).State = EntityState.Detached ' Detach from the initial context
        Return part
    End Using
End Function