這善有善報在實體框架拒絕讓程序員以更改數據保存順序的能力令人愉快的場景......實體框架外鍵衝突與Save_Changes
最終結果: 當我嘗試要保存我的更改(提交到SQLCE數據庫),我收到一個內部異常的錯誤: 「由於不存在對應的主鍵值,因此無法插入外鍵值[外鍵約束名稱=] 「
爲什麼發生這種情況: 我有一段VB.Net程序,它允許用戶與數據資源記憶中。就用戶而言,它看起來就像是在與數據庫交互。一旦他們完成了本部分的工作,他們可以保存/應用更改或取消它們。我選擇了這條路線來實現最簡單的「退出」,並減少了與數據庫的交互(我不希望在用戶更改內容時對數據庫進行不必要的插入/更新/刪除操作)。
通過取消,我只需使用上下文刷新方法從數據庫中重新加載EF數據,從而清除他們所做的任何事情。 通過保存/應用,我只需調用上下文的「Save_Changes」方法即可立即提交當前信息。 DB是本地SQLCE,只有具有單個用戶的應用程序正在訪問它。我並不擔心導致信息併發問題的多個連接。
這裏的問題是,我有3個表,每一個一對多的關係的層次結構: 表A 1 - > *表B 1 - > *表C
正在發生的事情是,EF試圖首先將DB中的更改保存到TableC,而不是TableA,等等。那麼.....這種做法會使DB中的FK約束不愉快,因爲DB約束(EF已經設置爲匹配),抱怨TableC中保存的條目不能存在,因爲TableB中引用的入口鍵不會不存在.....但是。實體框架很開心,因爲所有這些約束在內存中的EF模型中都得到了滿足,但它並沒有以正確的順序將它們提交給數據庫,因此違規。
我正在使用Visual Studio 2010 Express(限制我使用SQLCE 3.5)和.net 4.我已經運行了VSE 2010的所有當前Service Pack,並且據我所知,運行的是EF的最新版本由於我的項目引用仍然顯示.net 4.0.0.0,因此可以使用此設置。我試圖實現EF 5,但它似乎不適用於VSE 2010.
我是否僅僅需要從數據庫中刪除我的約束並僅將它們用於實體框架模型?我真的不喜歡這個選項,但是如果這個EF版本有一個錯誤,它按每個關係的錯誤順序提交給數據庫,那麼我想我沒有太多的選擇,直到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的約束條件,如果這確實是一個「順序」問題,那麼它仍然會被破壞,只是從TableB到TableA的約束;但是,它並沒有「打破」。
遍歷數據庫中保存的數據允許我識別來自文本文件的兩個條目,其中將在屬性表(TableC)中創建一個沒有Class表(TableB)中相應值的條目, 。因此,FK違規。
奇怪的是,這是如何不導致侵犯在進口過程中。
無論如何,我知道問題出在數據源中,我會添加邏輯來解決這個問題。正如Dabblernl所述,這個問題不在保存時間的EF順序中。
非常感謝大家的耐心。
如果您要發佈重現問題的代碼示例,您將有更好的機會獲得修復或解決問題。 – Paparazzi
根據我的經驗,EF確實始終獲得訂單權。所以也許問題是關係在模型中沒有被正確定義? – Dabblernl
我會很高興地添加代碼,我只是不知道哪個部分是相關的。這3個表正在通過添加來自文件的數據來填充,文件被正確地排序,以便沒有引用可以創建子條目適用的家長。 EF填充內存很好,直到調用Save_Changes時纔會彈出錯誤消息。如果我從數據庫中刪除FK約束,數據保存沒有問題。有一個版本的EF有這個錯誤關於在保存時反向獲取約束序列。 – user1654962