![](/img/trans.png)
[英]Table Per Concrete Type (TPC) Inheritance in Entity Framework 6 (EF6)
[英]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,需要多少更改?
結論:如果您有一個基類,則每個派生類都應在另一個表中引用該項目:將外鍵放在基類中。 但是,如果此關系不是所有派生項所固有的,則將外鍵放在派生類中。
請記住: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.