我正在开发一个使用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没有帮助,但请随意。
答案 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