0

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

这是该模式的示例。该接口是一个静态加载和一个实例保存(和删除——未显示)。

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 模式的尝试。

我也愿意接受有关如何使 Active Record 与 EF 一起使用的任何建议。这context.Entry条线很糟糕,但我不知道还能做什么。

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

4

1 回答 1

0

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

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
于 2012-05-14T21:32:31.717 回答