これは、Entity Framework がプログラマーがデータの保存順序を変更することを拒否するという楽しいシナリオを回避します...
最終結果: 変更を保存 (SQLCE DB にコミット) しようとすると、次の内部例外を含むエラーが表示されます:「対応する主キー値が存在しないため、外部キー値を挿入できません。[ 外部キー制約名 = ]"
原因: VB.Net プログラムに、ユーザーがメモリ内のデータを操作できるセクションがあります。ユーザーに関する限り、データベースと対話しているように見えます。このセクションでの作業が完了したら、変更を保存/適用するか、キャンセルすることができます。私はこのルートを選択して、最も簡単な「バックアウト」と DB とのやり取りを減らしました (ユーザーが変更を行っている間、DB への不要な挿入/更新/削除を行いたくありませんでした)。
キャンセルすることで、Context Refresh メソッドを使用して DB から EF データをリロードするだけです。保存/適用することで、コンテキストの「Save_Changes」メソッドを呼び出すだけで、現在の情報を完全にコミットできます。DB はローカル SQLCE であり、1 人のユーザーを持つアプリケーションのみがアクセスしています。複数の接続が情報の同時実行の問題を引き起こすことについては心配していません。
ここでの問題は、3 つのテーブルがあり、それぞれに 1 対多の階層関係があることです: TableA 1->* TableB 1->* TableC
何が起こっているのかというと、EF が DB の変更を最初に TableA ではなく TableC に保存しようとしているということです。ええと..... DB 制約 (EF が一致するように設定されている) は、TableB で参照されるエントリ キーが存在しないため、TableC に保存されているエントリが存在できないと不平を言うため、DB の FK 制約を不幸にします。存在しない……まだ。これらの制約はすべてメモリ内の EF モデルで満たされているため、Entity Framework は満足していますが、DB に正しい順序でコミットしていないため、違反になります。
私は Visual Studio 2010 Express (SQLCE 3.5 に制限されています) と .net 4 を使用しています。VSE 2010 の現在の Service Pack をすべて実行しており、私の知る限り、このセットアップで許可されている最新バージョンの EF を実行しています。私のプロジェクト参照にはまだ.net 4.0.0.0が表示されているためです。EF 5 を実装しようとしましたが、VSE 2010 では使用できないようです。
DB から制約を削除し、Entity Framework モデルでのみ使用する必要がありますか? 私はそのオプションが本当に好きではありませんが、この EF バージョンにバグがあり、関係ごとに間違った順序で DB にコミットしている場合、VSE 2012 がリリースされるまで選択肢はあまりないと思います。 ....
編集: これは、メモリ内のテーブルの作成を担当するコードです。読み取られるファイルには、親が追加されていないと子エントリが見つからないように順序が設定されています。
Dim lines() As String = IO.File.ReadAllLines(dlgOpen.FileName)
For Each line In lines
'Remove surrounding whitespaces
line = Trim(line)
'Identify if line is MIB, Class or an Attribute
If InStr(line, "MIB:", CompareMethod.Text) > 0 Then 'Found MIB entry
'Create new entry in the OID_MIB table
newMIB = SEDB.OID_MIB.CreateObject
curMIB = Guid.NewGuid
newMIB.M_ID = curMIB
newMIB.Name = Split_Line(line, 3)
newMIB.Description = ""
SEDB.OID_MIB.AddObject(newMIB)
MIBCount = MIBCount + 1
ElseIf InStr(line, "Class", CompareMethod.Text) = 1 Then
'Found Class entry
'Create new entry in the OID_Class table
newClass = SEDB.OID_Class.CreateObject
newClass.M_ID = curMIB
newClass.Name = Split_Line(line, 3)
newClass.OID = Split_Line(line, 2)
newClass.Description = ""
newClass.Tip = ""
SEDB.OID_Class.AddObject(newClass)
ClassCount = ClassCount + 1
ElseIf InStr(line, "attribute", CompareMethod.Text) = 1 Then
'Found Attribute entry
'Create new entry in the OID_Attribute table
newAttribute = SEDB.OID_Attribute.CreateObject
newAttribute.OID = Split_Line(line, 2)
newAttribute.C_OID = Get_ClassOID(newAttribute.OID)
newAttribute.Name = Split_Line(line, 3)
newAttribute.Description = ""
newAttribute.Tip = ""
newAttribute.Type = ""
SEDB.OID_Attribute.AddObject(newAttribute)
AttributeCount = AttributeCount + 1
End If
Next
概念モデルと DB の両方で制約が適切に設定されていることを確認する写真があればよいのですが、まだ写真を投稿するのに十分な評価ポイントがありません。
回答: そうですね......いくつかいじくり回した後、TableC と TableB のみの DB 側の制約を削除しました。これが実際に「順序」の問題である場合、それはまだ壊れています。 TableB から TableA への制約付き。しかし、それは壊れませんでした。
DB に保存されたデータをトラバースすると、テキスト ファイルからの 2 つのエントリを特定できました。これにより、クラス テーブル (tableB) に対応する値を持たない属性テーブル (TableC) にエントリが作成されます。したがって、FK 違反です。
奇妙なことは、これがインポート中に違反を引き起こさなかった方法です。
とにかく、データ ソースに問題があることはわかっているので、それを修正するロジックを追加します。Dabblernl が既に述べたように、問題は保存時の EF オーダーではありません。
皆様、ご辛抱いただきありがとうございました。