2012-04-03 134 views
28

嘿,我有一堆inproc緩存和實體框架的應用程序。當我想寫一個實體的更新時,我會重新附加緩存副本。我追蹤了我在上下文生命週期中所附加的所有內容,因此我不會嘗試附加它們兩次。實體框架:多對多關係中的參照完整性約束違規

我有發生在連接(在大多數情況下,很少能正常工作,是真的快)的錯誤,說以下內容:

參照完整性約束衝突發生了:該屬性定義 值參考約束在關係中的主體和從屬對象之間不一致 。

我仔細看過看起來很正常的實體。我認爲這個問題是由於fixup運行時外鍵的附件/分離造成的。

有沒有一種很好的方法來獲得有關此錯誤的更多信息,或者是否可以因爲實體未處於EF不期望的狀態而發生此類錯誤?

編輯: DB圖(注意:我使用codefirst我只是用EDMX工具,使圖中,我也砍傷了一堆常規性的關閉模式爲簡單起見)

enter image description here

+0

您是先使用代碼還是首先使用代碼 - 以及關於您擁有的模型的更多信息,與錯誤相關的表/類以及多對多映射。如果你先使用代碼,我更喜歡手動執行關係,這樣我就可以控制所有方面並避免類似的事情。另一方面,參照完整性錯誤可能意味着這一點 - 我不認爲它是對象的狀態,雖然它可能以我猜測的類似方式表現出來。 – NSGaga 2012-04-03 20:59:01

+0

即時通訊使用CodeFirst,我的模型非常簡單,生病發布圖表 – 2012-04-03 21:04:37

+0

盧克,你可以給CF部分,你如何映射事物 - 你的模型類是怎麼樣的,你的遷移代碼?爲了能夠幫助解決這個問題。 – NSGaga 2012-04-04 21:28:55

回答

40

對於PersonLocation之間的一對多關係,除了多對多關係之外,您顯然在模型中可能會出現錯誤。例如,下面的代碼會拋出異常:

using (var context = new MyContext()) 
{ 
    var person = new Person 
    { 
     CurrentLocationId = 1, 
     CurrentLocation = new Location { Id = 2 } 
    }; 
    context.People.Attach(person); // Exception 
} 

「定義引用約束的屬性值」是外鍵的屬性值CurrentLocationId和主鍵值CurrentLocation.Id。如果這些值不同,則拋出異常。 (雖然允許CurrentLocationnull雖然是允許的。)

在我看來這個異常只能引發外鍵關聯,因爲只有這種類型的關聯,你有在你的模型中定義參考約束的屬性。它不能被拋給獨立的協會。由於每個多對多關係都是一個獨立的關聯(模型中沒有外鍵屬性),我的猜測是錯誤與多對多關係無關,而是與一對多關係有關。

+1

那麼如何設置'位置'到'人'(給定位置ID)?在我的情況下,這是一個多對多的問題。這個例外的一般解決方案是什麼,我如何解決這個問題? – Shimmy 2013-06-08 21:37:00

+1

@Shimmy:或者將FK屬性設置爲只留下導航屬性爲'null'(我會在這種情況下做),或者確保設置爲導航屬性的實體的FK屬性值和PK值相同。但根據我的理解,這種例外情況不會發生在多對多的關係中。這是一個與FK關聯相關的例外,而多對多關係是獨立的關聯,而不是FK關聯。 – Slauma 2013-06-08 22:00:01

+0

在我的場景中,我有'類別'和'商務'。每個企業都可以有多個「類別」。我有我想要附加的類別ID列表,我該怎麼做? – Shimmy 2013-06-08 22:24:25

2

我剛剛遇到同樣的問題,我的解決方案是我已經添加了關聯的映射,然後設置引用contstraints。

爲了解決這個問題,我必須打開關聯的映射窗口,並且有一個鏈接來刪除映射。一旦完成映射細節窗口,然後說不允許映射。似乎添加引用約束會留下任何映射。

認爲可能值得發佈,以防其他人在未來尋找此錯誤消息的解決方案。

1

@LukeMcGregor喜,

我想我可以提供一個不同的視角,誰的人有同樣的問題。

在我執行了所有必要的檢查後,我可以說我更喜歡得到這個錯誤。

因爲在我的場景中:我想包含導致不匹配錯誤的對象。這是您場景中的位置對象。如果我添加一個帶有ID的對象,我會收到此錯誤,因爲上一個對象(未更新的對象)中的ID與更新的ID不匹配。

但這不是一個大問題。作爲解決方案;如果它仍然在UI端,那麼如果該對象仍然存在,則該對象可能仍然包含在內。

當您收到來自用戶的更新請求時,您將清空該對象。 (= Null)或者您將在服務端更新(附加,修改...任何)之前用用戶更新的ID更新對象並以這種方式更新它。

就是這樣。它可以保持原樣在數據庫和圖表中。

1

我在非常類似的異常來:

"A referential integrity constraint violation occurred: 
The property value(s) of 'ObjectA.PropertyX' on one end of a relationship 
do not match the property value(s) of 'ObjectB.PropertyY' on the other end." 

其原因是這樣的: 網絡API的客戶端發送與所述整個對象的PUT請求包括所述導航屬性(在該示例對象A(更正確的ObjectB.ObjectA)是一個導航屬性,並完全由客戶端提供)。發生這種情況的原因是,客戶端從服務器接收整個對象,並將其反彈回原來的服務器,並做了細微的更改。

另一方面,ObjectB.PropertyY剛剛改變(這是PUT請求的原因)。

由於ObjectB.PropertyY是對同一對象ObjectA(外鍵)的引用,因此EF試圖協調此操作,並且因上述異常而失敗。

將溶液簡單:

ObjectB.ObjectA = null; 

()完全解決了這個調用SaveChanges之前。

我希望這可以幫助別人。