簡體   English   中英

在Entity Framework Core中編寫實體POCO類的正確方法是什么?

[英]What is a proper way of writing entity POCO classes in Entity Framework Core?

EF Core默認具有“代碼優先心態”,即它應該以代碼優先的方式使用,即使支持數據庫優先方法,它也只是對現有數據庫進行逆向工程和創建代碼優先表示。 我的意思是,在代碼“手工”(代碼優先)中創建並從數據庫(通過Scaffold-DbContext命令)生成的模型(POCO類)應該是相同的。

令人驚訝的是,官方EF Core文檔顯示出顯着差異。 下面是在代碼中創建的模型的例子: https://ef.readthedocs.io/en/latest/platforms/aspnetcore/new-db.html這里是逆向工程從現有的數據庫它的例子: HTTPS: //ef.readthedocs.io/en/latest/platforms/aspnetcore/existing-db.html

這是第一種情況下的實體類:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

這是第二種情況下的實體類:

public partial class Blog
{
    public Blog()
    {
        Post = new HashSet<Post>();
    }

    public int BlogId { get; set; }
    public string Url { get; set; }

    public virtual ICollection<Post> Post { get; set; }
}

第一個例子是一個非常簡單,非常明顯的POCO類。 它在文檔中隨處可見(除了從數據庫生成的示例)。 第二個例子有一些補充:

  • 類被聲明為部分 (即使沒有任何地方可以看到它的另一個部分定義)。
  • Navigation屬性的類型為ICollection <T> ,而不僅僅是List <T>。
  • Navigation屬性在構造函數中初始化為新的HashSet <T>() 在代碼優先的例子中沒有這樣的初始化。
  • 導航屬性聲明為虛擬
  • 生成的上下文類中的DbSet成員也是虛擬的

我已經嘗試過從數據庫中構建模型(截至本文撰寫時的最新工具)並且它完全按照所示生成實體,因此這不是一個過時的文檔問題。 因此官方工具生成不同的代碼,官方文檔建議編寫不同的(普通的)代碼 - 沒有部分類,虛擬成員,構造初始化等。

我的問題是,嘗試在代碼中構建模型,我應該如何編寫代碼? 我喜歡使用ICollection而不是List,因為它更通用,但除此之外,我不確定我是否需要遵循文檔或MS工具? 我需要將它們聲明為虛擬嗎? 我是否需要在構造函數中初始化它們? 等等...

我從舊的EF時代就知道虛擬導航屬性允許延遲加載,但在EF Core中甚至不支持它(並且我不知道任何其他用途)。 也許它會影響性能? 也許工具試圖生成面向未來的代碼,這樣當實現延遲加載時,POCO類和上下文將能夠支持它嗎? 如果是這樣,我可以拋棄它們,因為我不需要延遲加載(所有數據查詢都封裝在一個回購中)?

不久,請幫助我理解為什么不同,在代碼中構建模型時應該使用哪種樣式?

我試着簡單回答你提到的每一點

  • partial類對工具生成的代碼特別有用。 假設您要實現僅模型派生屬性。 對於代碼優先,您只需要在任何地方執行此操作。 對於數據庫優先,如果更新模型,將重寫類文件。 因此,如果您想保留擴展代碼,則需要將其放在托管模型之外的其他文件中 - 這是partial幫助您擴展類而無需手動調整自動生成的代碼的地方。

  • ICollection絕對是一個合適的選擇,即使是代碼優先。 如果沒有排序語句,您的數據庫可能不會支持已定義的訂單。

  • 構造函數初始化至少是一種方便...假設您有一個數據庫方式的空集合,或者您根本沒有加載該屬性。 如果沒有構造函數,則必須在代碼中的任意點處明確地處理null情況。 你是否應該使用ListHashSet是我現在無法回答的問題。

  • virtual支持為數據庫實體創建代理,這可以幫助您完成兩件事:如您所述的延遲加載和更改跟蹤。 代理對象可以使用setter立即跟蹤虛擬屬性的更改,而上下文中的普通對象需要在SaveChanges上進行檢查。 在某些情況下,這可能更有效(通常不是)。

  • virtual IDbSet上下文條目允許更輕松地設計單元測試的測試模型上下文。 其他用例也可能存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM