2009-09-01 75 views
7

我有一個基礎Employee實體和特定僱員類型的一些派生實體的繼承層次結構。我需要能夠將基礎Employee實體轉換爲更具體的實體(例如TemporaryEmployee),並從更具體的類型轉換回基本類型(例如,如果員工不再是「臨時」的,那麼我希望該實例只是持久化爲Employee 在數據庫中,這只是從表中爲特定子類添加或刪除一行的問題(我使用的是每個類的表)。但是我沒有看到如何使用EF調用來完成此操作更改屬於繼承層次結構一部分的(實體框架)實體的類型

回答

4

從技術上講,您可以通過使用存儲過程來實現它。 TPT不支持它。

但是,我完全同意克雷格。在經典的編程書籍設計模式(Addison-Wesley Professional)中,作者討論了繼承與構圖,並得出結論認爲應該「贊成構圖而不是繼承」。

+0

是的,現在我已經使用存儲過程實現了這一點。 這也是MSFT的建議: 「你不能直接在實體框架中這樣做,你最好的選擇是編寫存儲過程來完成這些轉換」 http://social.msdn.microsoft.com/Forums/ EN-US/adodotnetentityframework /線程/ 860d7913-7baa-43e9-a2a7-83b25ad9c558 / – 2009-09-01 20:55:45

7

OOP的原理之一是實例不能改變它們的類型。想一下:你可以用普通的.NET對象來做這件事嗎?當然不是。堅持他們與EF,要麼

向數據庫添加一行不會改變實例的typ e,要麼;它只是EF的謊言,關於你保存的東西。在關係域中,您添加了一個關係,而不是更改對象的類,因爲關係域不知道對象。

因此,長期和短的是,使用EF不會改變.NET規則,即實例不能改變它們的類型。

當你需要這樣做時,你應該怎麼做?那麼,想想這是如何工作在你的問題領域。員工是一個人。他們的就業狀況與該人有關,但他們的身份實際上並不是人。

使用組合而不是繼承。我可能會將此模型設置爲Person,並帶有一系列Employment實例。當一個人的就業情況發生變化時,您可以將停止/終止日期分配給舊記錄,併爲新作業添加新記錄。

我碰巧讀了this blog post今天早上,這可能是進一步的思考。

編輯爲添加如果您通過實施DB存儲過程來解決此問題,請確保沒有人在執行時實際使用系統。因爲這在.NET對象空間中是完全非法的,所以實體框架認爲它不可能發生。如果您繞開實體框架並執行此操作,並且用戶碰巧有一個活動的ObjectContext,則此實體框架中的正常樂觀併發保護未檢測到此ObjectContext與數據庫不同步。您不會損壞數據,但具有活動ObjectContext的用戶可能會看到一些令人難以置信的奇怪錯誤。

+1

好評。繼承在這裏似乎更自然,因爲它允許我定義更具體的類型之間的關係。 是的,你也鏈接到有趣的博客文章 - 將實體更改爲基本類型是一種刪除形式 - 也許我不應該這樣做...... – 2009-09-01 20:53:27

+0

關於您添加的編輯:EF不會並且不能假設它是更新數據庫的唯一過程。事實上,在大多數情況下,它不是 - 您可能至少有多個ObjectContext實例針對同一個數據庫(例如,在Web應用程序中每個用戶一個)運行。 – 2009-09-02 15:56:58

+0

我沒有說EF假定它是更新數據庫的唯一過程,因爲那是錯誤的。我說,當某些外部進程「損壞」數據庫時,它會返回奇怪的錯誤消息。考慮到很多原因,EF考慮將實例的類型改爲腐敗。這只是一個問題,如果(1)與內存中的對象存在活動對象上下文,則(2)其他用戶「改變類型」,然後(3)原始上下文對對象執行某些操作。 EF將檢測到問題並返回高度技術性錯誤。就像我說的那樣,這樣做並不是多用戶安全的。 – 2009-09-02 16:23:38