ADO.NET (raw 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(...)
2行を削除すると、正常に機能します。
私が気付いていないコンテキストの外にあるタイプの変更トラッカーはありますか? それは、Active Record パターンでのあらゆる試みを殺してしまうようです。
Active Record を EF で動作させる方法についての提案もお待ちしています。ラインはひどいですが、context.Entry
他に何をすべきかわかりません。
Active Record をしないように言っても何の役にも立ちませんが、遠慮なく言ってください。