是的,你可以在實體框架使用繼承。但是,數據庫通常不支持繼承。在數據庫中,繼承是嘲弄的。有幾種策略用於模擬繼承。
假設你有三類:
public class MyBaseItem {...}
public class MyDerived1Item : MyBaseItem {...}
public class MyDerived2Item : MyBaseItem {...}
策略表每個具體類(TPC) 我用這一個最常用,如果我不需要創建MyBaseItem對象,只有MyDerived1Items或MyDerived2Items。爲了防止意外創建MyBaseItem對象,我聲明瞭MyBaseItem摘要。
該數據庫將有兩個表:一個帶有MyDerived1Items,另一個帶有MyDerived2Itemss。兩個表都將有所有MyBaseItem屬性的列。
Fluent API用於通知數據庫生成器該策略已被使用。
public MyDbContext : DbContext
{
public DbSet<MyDerived1Item> MyDerived1Items {get; set;}
public DbSet<MyDerived2Item> MyDerived2Items {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyDerived1Item>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("MyDerived1Items");
});
modelBuilder.Entity<MyDerived2Item>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("MyDerived2Items");
});
}
}
添加/修改/數據庫中刪除的項目將總是意味着訪問一個表,除非你想要做的所有衍生商品的MyBaseItems性質的東西。在這種情況下,你必須給每個派生表的元素鑄成MyBaseItem和Concat的所有派生表,如下所示:
IQueryable<MyBaseItem> someBaseItems =
dbContext.MyDerived1Items.Where(...).Cast<MyBaseItem>()
.Concat(dbContext.MyDerived2Items.Where(...).Cast<MyBaseItem>();
這是很容易在以後添加MyDerived3Items表。 MyDerived1Items和MyDerived2Items表不必更改。
但是,將一個屬性添加到MyBaseItem意味着將一個字段添加到派生類的所有表中。
策略表每類型(TPT)
創建三個表。每種類型都有一張桌子。包含派生項目的表格具有包含基本項目的表格的外鍵。
如果您創建了MyDerived1Item,那麼該對象將被放在兩個表中。基類的MyBaseItem屬性將位於MyBaseItems表中,並且MyDerived1Item屬性將位於MyDerived1Items表中,並與MyBaseItem中的相應項的外鍵一起使用。
我不喜歡這種方法,因爲它看起來非常像一對多關係。在數據庫中有可能有一個基項與兩個派生項具有相同的外鍵,這不是你想要的。我不確定是否可以阻止將這樣的對象添加到數據庫中。
添加/搜索/更改/刪除項目始終意味着使用兩個表格,這會使這些操作變得更慢。
但是,這種方法的優點是您可以創建MyBaseItems。所以如果你需要這樣做,考慮這個策略。每層次
How to implement Table Per Type (TPT)
表(TPH)
這種策略是實體框架的缺省值。
數據庫將有一個包含MyBaseItem,MyDerived1Item和MyDerived2Item的所有屬性的表。未使用的列被設置爲NULL。如果MyDerived1Items與MyDerived2Items幾乎相同,那麼不會有太多多餘的列。但是,如果這兩個類非常不同,那麼會有很多列設置爲空。
你將有一個表,你將有一個DbSet:
public class MyDbContext: DbContext
{
public DbSet<MyBaseItem> MyItems { get; set; }
}
因爲這是默認的策略,不需要流暢API。
如果你需要的是隻使用基本屬性的查詢:
IQueryable<MyBaseItem> baseItems = dbContext.MyItems
.Where(...);
如果您只需要MyDerived1Items:
IQueryable<MyDerived1Item> myItems = dbContext.MyItems
.OfType<MyDerived1Items>()
.Where(...);
,如果你希望有大量的查詢,只有基本屬性考慮這一策略,因爲這隻能訪問一個表。如果你的派生類非常不同,請重新考慮它。
試一試,讓我們知道! – Maarten
@Maarten我知道我可以嘗試看看它是否有效。我擔心這可能會起作用,但是可能是一種糟糕或錯誤的做法,並會在項目的後期部分給我造成麻煩。 –
我建議閱讀[EF Code First的繼承](https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table- per-hierarchy-tph)系列。 –