我們有一個數據庫,其中一個表包含的記錄可以是其他幾個表的子記錄。它有一個「軟」外鍵,由所有者的ID和一個表名組成。這種(反)模式被稱爲「多態關聯」。我們知道這不是最好的數據庫設計,我們會在適當的時候改變它,但不會在不久的將來。讓我給一個簡單的例子:建模多態關聯數據庫優先與代碼優先
兩個Event
,Person
和Product
在評論記錄。正如你所看到的,沒有硬性的FK限制。
在實體框架可以通過sublassing Comment
到EventComment
等方面給予支持這種模式,讓Event
有EventComments
收集等:
的子類和關聯是後手動添加從數據庫生成基本模型。 OwnerCode
是此TPH模型中的鑑別器。請注意,Event
,Person
和Product
是完全不同的實體。爲他們建立一個共同的基類是沒有意義的。
這是數據庫優先。我們的現實生活模式是這樣的,沒問題。
好的。現在我們要轉向代碼優先。因此,我開始將數據庫逆向工程化爲代碼優先模型(EF Power Tools),並繼續創建子類並映射關聯和繼承。試圖連接到Linqpad的模型。那時麻煩就開始了。
當試圖用這個模型來執行一個查詢,它拋出一個InvalidOperationExeception
國外關鍵部件「OWNERID」不在類型「EventComment」聲明的屬性。驗證它沒有被明確地從模型中排除,並且它是一個有效的基本屬性。
發生這種情況時,我有雙向協會和OwnerId
被映射爲Comment
的屬性。在我EventMap
類(EntityTypeConfiguration<Event>
)的映射是這樣的:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
於是,我就聯想沒有OwnerId
模型映射:
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
這將引發MetaDataException
指定的模式無效。錯誤: (10,6):錯誤0019:類型中的每個屬性名稱都必須是唯一的。屬性名稱'OwnerId'已經定義。 (11,6):錯誤0019:類型中的每個屬性名稱都必須是唯一的。屬性名稱'OwnerId'已經定義。
如果我刪除三個實體 - 評論關聯中的兩個,這是可以的,但當然這不是治癒。
一些進一步的細節:
- 它可以通過添加的DbContext發生器項從EDMX創建工作的DbContext模型(「第二碼」)。 (這將暫時解決)。
- 當我將工作代碼優先模型(帶有一個關聯)導出到edmx(
EdmxWriter
)時,關聯看起來在存儲模型中,而在原始的edmx中它們是概念模型的一部分。
那麼,我該如何創建這個模型代碼優先?我認爲關鍵是如何指示代碼優先來映射概念模型中的關聯,而不是存儲模型。
您是否曾經使用過Code-First的模型?有趣的是,它適用於Db-First/EDMX。我有一個關於類似模型的問題,CodePlex的最終詞語基本上是「不支持」和「基本EF限制」(http://stackoverflow.com/a/14880084/270591)。但是如果你的模型與EDMX一起工作,它實際上似乎是Code-First的限制,而不是一般的EF限制。 – Slauma
是的,數據庫優先模型的作品(感謝上帝)。真正的模型甚至更復雜,因爲它具有複合繼承鑑別器。沒問題。第一個代碼是問題。你有沒有試過你的模型db-first? –
不,從來沒有嘗試過。我們知道Code-First不支持所有的edmx特性,但我真的沒有想到這種情況會有所不同。我有btw只是要求在CodePlex上的舊問題確認(https://entityframework.codeplex.com/workitem/865,在頁面上的最後一個評論)。不確定我是否可以在封閉的項目中得到答案。 – Slauma