我有一個博士學位。在cs中 - 在數據庫領域,所以這個答案會有點不同於程序員的觀點。對於Oliver Hanappi來說,如果它不是代理鍵,那麼一個關鍵可以偶爾也會改變。例如。一個自然鍵或一個合成鍵。例如。有可能在美國更改SSN。但是很多程序員多年來一直認爲這是一個不可改變的關鍵,並將其用於此。更改由外鍵組成的複合主鍵更爲常見。
我在處理一個具有三元關係的數據庫。具體來說有三個實體(外鍵在它們各自表中的代理主鍵)。但是,要保留兩個實體之間的關係,同時更改第三個實體需要更改部分交集表(也稱爲MSDN上的純聯接表)主鍵。這是一個有效的設計,只能通過刪除三元關係交點表並用兩個二元關係表(可能有它們自己的代理鍵)替換它來改進。 EF會處理這個罰款。這種設計變更會使(Many-> many) - > many或Parent1-Parent2 - > Child-grandchild模型(如果不清楚,請閱讀下面的示例)。實體框架可以正常工作,因爲每個關係實際上都是一對多的關係。但從數據庫的角度來看這是一個瘋狂的設計。讓我告訴你一個例子爲什麼。
考慮課程,課堂和講師在課堂上彼此關聯。 Class可以包括:CourseID,ClassroomID,InstructorID作爲外鍵,幷包含一個包含所有三個鍵的組合主鍵。雖然一個清晰,簡潔的三元模型(3路關係),我們可以將其分解爲二元關係。這會得到兩個相交表。
類(SurrogateKeyClass,InstructorID,CourseID)
ClassRoomUsed(SurrogateKeyClassroomUsed,SurrogateKeyClass,ClassRoomID)
的:如下添加代理鍵將滿足EF這個設計的問題是我們可以有相同的課程和講師相關的mult這是以前的模型避免的時間。爲了避免這個問題,你可以在數據庫中添加一個約束來保證兩個ID字段的唯一性,但是爲什麼當你只處理代理鍵開始的時候,你會這麼做?然而,這個解決方案將盡我所能地工作。然而,這不是邏輯數據庫設計,因爲DB中需要不自然的唯一約束。
但是,如果你不想改變你的數據庫或不能改變你的數據庫,這裏是一個第二個解決方案:路口/關聯表是正義的,鏈接連接兩個實體或更多在一起。如果更改,請刪除關聯並重新創建一個具有適當外鍵(導航屬性)的新關聯。這意味着你不會被允許在任何關係中要求兒童實體,但這是非常普遍的。
我會建議實體框架(在未來)允許我們這些誰可以設計一個優雅的數據庫模型來改變我們想要的交集/關聯表中的部分鍵!
另一個例子免費:
考慮一個學生,當然,等級協會。學生通過一個等級與課程相關聯。通常這是學生和課程之間的多對多關聯,並在關聯表中添加了一個稱爲等級的附加字段(關聯表具有有效載荷數據,例如等級,交叉表不具有有效載荷,並且在MSDN中被稱爲純連接表租賃在一個地方):
學生(StudentID,....)
場(CourseID,...)
服用(StudentID,CourseID,級)
如果有人從下拉使得數據錄入錯誤,並把學生在錯誤的類,你喜歡他們通過選擇日後變更再次下拉並選擇不同的課程。在後臺,您需要從Taking表中刪除EF對象,並重新創建它,而不會丟失成績(如果有的話)。只需更改外鍵CourseID似乎是一個更好的選擇。如果這個人看起來有些做作,可以拿出你自己的協會,但作爲教授,這對我來說很自然。
結論:當你有一串關係時,最好不要允許級聯和/或改變FK,但是在需要時存在合理/合理的場景,即使不推薦作爲的最佳實踐一般。
這個問題可能會表現有以下例外取決於如果要更改導航屬性或模型分別關鍵屬性:
參照完整性約束衝突發生了:主鍵屬性,它是一個組成部分如果依賴對象未更改,除非將其設置爲關聯的主體對象,否則無法更改參照完整性約束。主要對象必須被追蹤並且不被標記爲刪除。
屬性'X'是對象的關鍵信息的一部分,無法修改。
請問爲什麼要改變主鍵,這是非常非常非常糟糕的做法。 – 2009-09-02 13:46:21
好問題。我們通過匿名的customerid在數據庫中跟蹤匿名信息。當用戶登錄時,我想更新表格並將其設置爲其常規customerid。 – 2009-09-02 13:49:49
只是我,我會有兩個表爲匿名用戶之一,然後他們登錄時在主表中創建一個新的記錄,但永遠不會修改主要。 – 2009-09-02 13:51:39