簡體   English   中英

首先使用EF代碼進行繼承-每個具體類型(TPC)的表

[英]Inheritance with EF Code First - Table per Concrete Type (TPC)

按每種混凝土類型(TPC)結構創建了這種 ,如下所示:

在此處輸入圖片說明

這里是這里使用的實體:

public abstract class BaseModel : MyOtherBaseClass
{
    [Key]
    public int Id { get; set; }

    //Foreign key for Project
    public int ProjectId { get; set; }

    public int Sequence { get; set; }

    public string Name { get; set; }

    public string IconUrl { get; set; }

    //Navigation Properties ####################
    public virtual Project Project { get; set; }
}


[Table("Tool")]
public class Tool : BaseModel
{
    [Key]
    public int Id { get; set; }

    public string ToolBrand { get; set; }

    //Navigation Properties ####################
    //public virtual Project Project { get; set; }
}


[Table("Priority")]
public class Priority : BaseModel
{
    [Key]
    public int Id { get; set; }

    public string PriorityCode { get; set; }

    //Navigation Properties ####################
    //public virtual Project Project { get; set; }
}

在這一點上,我對以下問題感到困惑:

1)我可以對工具和優先級實體使用ID嗎? 而且這絕對是不必要的嗎?

2)我在BaseModel類中使用FK(ProjectId)和相關的表Project。 但是,由於將在“工具”和“優先級”表中創建ProjectId列,因此如何創建關系? 可能有什么問題嗎?

3)如果我不喜歡Fluent API,是否應該在上下文中添加BaseModel實體之外的Tool和Priority實體? 因為在某些資源中添加了子類,而在另一些資源中則沒有。 哪一個是對的?

public class EntityContext : DbContext
{
    public DbSet<BaseModel> BaseModel { get; set; }
    // ? public DbSet<Tool> Tool { get; set; }
    // ? public DbSet<Priority> Priority { get; set; }
}

如果對此用法有任何問題,也可以讓我知道嗎? 謝謝...

每當您設計類時,您都應該知道類的真正含義。

您的DbSet<...>代表數據庫的一個表。 DbSet的類將該表的列表示為非虛擬屬性,並將表之間的關系表示為虛擬屬性。

在我看來,您需要數據庫中的兩個表:一個帶有Tools的表和一個Priorities的表。 您目前認為“ Tools某些列也位於“ Priorities 因此,您打算創建一個通用的基類,其名稱沒有比BaseModel更好的名稱。

您不能為通用基類發明合適的名稱這一事實應該警告您,也許這兩者之間並沒有真正的通用之處。 您確定,如果描述的是Tool ,那不是偶然的事情,它具有與Priority相同名稱和類型的某些屬性

例如。 如果要定義“ Tools行和“ Priorities行,則可以說每個“ Tool都在Project ,每個“ Priority級”都是Project的優先級。 這是系統設計的一部分。 根據您的定義,沒有其Project Tools是沒有意義的

即使如此,根據您的定義,每個工具都應該有一個“唯一標識方法”,您決定為此使用整數ID。 同樣,您決定為優先級設置一個整數ID。 但是,標識的類型等於優先級的標識的類型對您的Tool表中的行而言是固有的嗎? 如果有人告訴您“ Tool具有Guid ID,而“ Priority具有整數Id,您是否希望設計毫無價值?

當然沒有:您的設計應該如此健壯,以至於數據庫表中的細微變化都應該導致設計中的細微變化!

哪些屬性應在基類中

1)我可以對工具和優先級實體使用ID嗎?

答:是的,您可以將Id放在基類中,並從派生類中忽略它。 但是,這將增加一個約束,即每個派生類型的表中代表Id的列應具有相同的名稱和類型。

因此:如果您不希望局限於此:不要這樣做,請從基類中刪除ID並將其放在派生類中。 如果以后有人決定進行較小的更改以重命名該列,或者給它提供其他類型,則您的更改將很小。

當然,這也適用於所有其他屬性:如果它們“巧合”相同,則將值放在派生類中。 如果“ Tools和“ Priorities都具有共同點,則將其放在基類中。

對我來說,要檢測項目的工具與項目的優先級之間的相似性並不容易,因此我將切換到另一個示例。

假設您有一個包含“教師和學生”的數據庫。 有些屬性對於教師是唯一的,而某些屬性對於學生是唯一的。 但他們也有一些共同點,並非巧合:老師和學生都是人,都有名字,生日,可能還有地址等。如果后來有人決定某個地址有一個額外的字段,指示該地址的GPS坐標,那么您只需更改一個班級。

結論:僅將對所有派生類都固有的內在屬性放在基類中,而不是巧合

外鍵放在哪里?

根據您的設計,“工具”和“優先級”均屬於項目。 如果在上一步之后您確定這是它們唯一的共同點,那么您將很少使用一堆同時包含“工具”和“優先級”的對象。

在學校數據庫中,將學生和教師分成一群人是很正常的,其中每個人都有一個地址,而每個地址中將居住零個或多個人(一對多)

// this will be a row in a table, hence it has an Id
class Address
{
     public int Id {get; set;}
     public string ZipCode {get; set;}
     public string Street {get; set;}
     ...

     // on every address live zero or more Persons (one-to-many)
     public virtual ICollection <Person> Persons {get; set;}
}

// this will not be a row in a separate table, hence it has no ID
class Person
{
     public string Name {get; set;}
     public DateTime Birthday {get; set;}
     ...
     // every Person lives at an Address, using foreign key
     public int AddressId {get; set;}
     public virtual Address Address {get; set;}
}

class Teacher : Person
{
    public int Id {get; set;}
    ...
}
class Student: Person
{
    public int Id {get; set;}
    ...
}

因此,您將擁有三個表:地址,教師,學生。 老師和學生都將具有一個人的屬性。 他們倆都住在一個地址。

看看如果我們決定在“教師”或“人”中添加一列,幾乎不需要進行任何更改? 如果您希望教師ID為GUID或Address.Id為字符串(需要更改地址的主鍵和Person內部的外鍵),則幾乎不需要更改。 看看您想添加新的Person類型:Parent,需要多少更改?

結論:如果您有一個基類,則每個派生類都應在另一個表中引用該項目:將外鍵放在基類中。 但是,如果此關系不是所有派生項所固有的,則將外鍵放在派生類中。

3我應該在上下文中添加除BaseModel實體之外的實體嗎?

請記住:DbContext中的每個DbSet都將成為一個表。 如果您未將“工具和優先級”指定為單獨的表,則不會使用“ 每個創建類的表(TPC)”,而是使用“ 每個層次結構的表”(TPH) :“工具”和“優先級”都將在一個表中

我很少使用TPH,因為我在表中得到的所有未使用的空值。

如果您最經常要求“教師為...”和“學生為...”,則應將其放在單獨的表格中。 基類的列也位於這些單獨的表中。

如果您最經常詢問“ ...的人”,則“人”可能是學生或教師,請考慮使用“ 每種類型的表”(TPT) :“人”表和帶有“人”表外鍵的“教師”表,以及帶有外鍵的學生表。 所有基類屬性都在“人員”表中。

很容易看到,如果您要求“ Persons that ...”,TPT將只查詢一個表,而對於TPC,則需要查詢Teachers表和Student表並連接結果。

但是,如果您要求“ Students that ...”,則TPT將需要加入Persons表和Students表。 TPC的速度更快:僅訪問一個表。

暫無
暫無

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

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