EF4 程式碼優先:定義對象關係、外鍵
< RANT_MODE >
EF 程式碼優先方法旨在節省大量時間,但目前我只看到玩具範例並花費數小時試圖了解如何使其生成我想要的數據庫。但仍然希望尤里卡時刻:-)
< RANT_MODE />
關於問題!
虛擬與具體屬性
我試圖了解 EF 如何映射和檢索對象關係。我應該什麼時候標記一個屬性
virtual,什麼時候不?(如在public Person Owner { get; set; }vs.中public virtual Person Owner { get; set; }。)在我見過的數十個程式碼優先範例中,他們似乎可以互換使用這些範例,但沒有太多解釋。我所知道的是導航屬性 (public virtual ICollection<Person> Owners { get; set; }) 必須是virtual為了使延遲載入成為可能(正確..?),但這在非收藏品世界中如何應用?對象關係和外鍵
public int OwnerId { get; set; }除了我感興趣的“主要”屬性()之外,我找不到任何關於是否應該包含外鍵欄位( )的資訊public Person Owner { get; set; }。我嘗試不這樣做,並且 EF 友好地自動添加了一個 int 列Owner_Id在我的表中命名,似乎理解我想要實現的目標。在Code First 的約定(“外鍵”部分)中,EF 團隊提到“在關係的依賴端包含外鍵屬性是很常見的”,並且“Code First 現在將推斷任何名為 ’’ (即 OwnerId)[…] 具有與主鍵相同的數據類型,表示關係的外鍵”。IE。如果我有兩個 EF 就會知道它們是相關的。
但是,除了“外來對象”本身之外,明確指定持有 FK 的此類屬性是否被認為是一種好的做法?
外來對象、外鍵 - 續
正如我上面提到的,即使我只有
public Person Owner { get; set; }在我的對像中(比如Event),該表Events也會包含一個Owner_Id由 EF 自動添加的列。更重要的是,檢索後我將可以訪問Owner.但是,請考慮以下情況。我有兩個課程:
public class Account { public int Id { get; set; } public Person Owner { get; set; } } public class OpenIdAccount : Account { public string Identifier { get; set; } }我希望它們與 TPT 相關。這意味著手動映射:
modelBuilder.Entity<Account>().MapHierarchy(a => new { a.Id, Owner_Id = a.Owner.Id }).ToTable("Account"); modelBuilder.Entity<OpenIdAccount>().MapHierarchy(a => new { a.Id, a.Identifier }).ToTable("OpenIdAccount");您可能會注意到,我試圖重新創建 EF 對我的
Owner_Id專欄所做的事情。然而在檢索時,myAccountInstanceFromDb.Owner為空。這是為什麼?我如何告訴 EF 它應該發揮它的魔力並填充我的Owner財產?指針,指針
如果您能澄清上述內容,我將不勝感激 - 達到了真正希望知道答案的地步,但無法閱讀另一篇文章,該文章只是展示了另一個玩具範例,說明使用 EF 是多麼容易。也就是說,如果您確實對 EF 的大腦有深入的最新參考,請也發布連結。
提前感謝您的寶貴時間!
虛擬與最終屬性:
這實際上與程式碼無關,這是 EF 和 POCO 的主題:當您擁有 POCO 時,您會失去對導航屬性的大量 EF 支持,您可以通過將它們設為虛擬來選擇加入它們。這允許 EF 在執行時創建代理,並通過覆蓋該代理類中的導航屬性為您提供支持。這些支持是更改通知、關係修復和延遲載入。
延遲載入對 Collection 和非 Collection 類型的導航屬性的工作方式相同。此外,始終將導航屬性標記為虛擬也是一種很好的做法。
外鍵關聯或獨立關聯
EF3.5 不支持關聯中的 FK 並將其隱藏(也稱為獨立關聯)。EF4 開始支持關聯中的 FK(又名外鍵關聯)。取決於您喜歡哪一個,您可以顯式包含或不包含 FK 屬性,但除了導航屬性之外,顯式指定 FK 屬性絕對是一種好習慣,因為它為您提供了使用對象的最大靈活性。
檢索後,myAccountInstanceFromDb.Owner 為空。這是為什麼?我如何告訴 EF 它應該發揮它的魔力並填充我的 Owner 屬性?
當然,您沒有將其標記為虛擬,因此不支持延遲載入,但您也沒有明確地預先載入或延遲載入它。要解決此問題,請使用virtual關鍵字並讓 EF 為您延遲載入它,或者使用Include方法在整個對象物化時預先載入它。
標量屬性與導航屬性
標量屬性是其值包含在實體中並與表列相對應的屬性(例如 Account.Id)。
導航屬性只是指向相關實體的指針。例如,Account 實體有一個 Owner 屬性,該屬性將使應用程序能夠從一個 Account 導航到擁有該 Account 的 Owner。
因此,回到您的問題,您需要做的就是將導航屬性指定為
virtual Person Owner並可選擇指定 FK 屬性為int OwnerId,您就可以開始了。