Entity?Framework映射TPH、TPT、TPC與繼承類(lèi)
一、TPH
Table Per Hierarchy (默認(rèn),每個(gè)層次一個(gè)表)
每個(gè)層次結(jié)構(gòu)共用一個(gè)表,類(lèi)的每一個(gè)屬性都必須是可空的。
1、默認(rèn)行為
只建立一個(gè)表,把基類(lèi)和子類(lèi)中的所有屬性都映射為表中的列。
為基類(lèi)和所有子類(lèi)共建立一個(gè)表,基類(lèi)和子類(lèi)中的所有屬性都映射為表中的一個(gè)列。
默認(rèn)在這個(gè)表中建立一個(gè)叫做Discriminator的列,類(lèi)型是nvarchar,長(zhǎng)度是128。在存儲(chǔ)基類(lèi)或子類(lèi)的時(shí)候,把類(lèi)名作為Discriminator列的值。
2、Fluent API修改默認(rèn)行為
Map方法中傳入的類(lèi)型參數(shù)是子類(lèi)的類(lèi)名,Requires用于指定Discriminator列的名字,HasValue用于指定它的類(lèi)型和每個(gè)子類(lèi)對(duì)應(yīng)的值。
modelBuilder.Entity<Course>() .Map<Course>(m => m.Requires("Type").HasValue("Course")) .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));
二、TPT
Table Per Type(每個(gè)類(lèi)各一個(gè)表)
1、默認(rèn)行為
為基類(lèi)和每個(gè)子類(lèi)各建立一個(gè)表,每個(gè)與子類(lèi)對(duì)應(yīng)的表中只包含子類(lèi)特有的屬性對(duì)應(yīng)的列。
子類(lèi)的表中只包含子類(lèi)特有的屬性,子表還會(huì)存儲(chǔ)一個(gè)將子表與基表聯(lián)接的外鍵。
2、Fluent API修改默認(rèn)行為
我們可以使用Map方法強(qiáng)制讓Code First使用TPT方式,因?yàn)镃ode First默認(rèn)使用的是TPH方式。
modelBuilder.Entity<Course>().ToTable("Course"); modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");
三、TPC
Table Per ConCrete Type(每個(gè)具體類(lèi)型各一個(gè)表)
每個(gè)具體的派生類(lèi)各一個(gè)表,沒(méi)有基表。不推薦使用。
1、默認(rèn)行為
在子類(lèi)對(duì)應(yīng)的表中除了子類(lèi)特有的屬性外還有基類(lèi)的屬性對(duì)應(yīng)的表。基類(lèi)可以是abstract。
2、Fluent API修改默認(rèn)行為
通過(guò)MapInheritedProperties方法就可以強(qiáng)制Code First使用TPC方式。
注意:因?yàn)閷儆?TPC 繼承層次結(jié)構(gòu)的表并不使用同一個(gè)主鍵, 關(guān)閉主鍵屬性的標(biāo)識(shí),避免為不同子表插入重復(fù)的實(shí)體鍵。
modelBuilder.Entity<Course>() .Property(c => c.CourseID) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); modelBuilder.Entity<OnsiteCourse>().Map(m => { m.MapInheritedProperties(); m.ToTable("OnsiteCourse"); }); modelBuilder.Entity<OnlineCourse>().Map(m => { m.MapInheritedProperties(); m.ToTable("OnlineCourse"); });
四、實(shí)體拆分
允許一個(gè)實(shí)體類(lèi)型的屬性分散在多個(gè)表中。
實(shí)體拆分通過(guò)多次調(diào)用 Map 方法將一部分屬性映射到特定表。
在以下示例中,Department 實(shí)體拆分到兩個(gè)表中:Department 和 DepartmentDetails。
modelBuilder.Entity<Department>() .Map(m => { m.Properties(t => new { t.DepartmentID, t.Name }); m.ToTable("Department"); }). Map(m => { m.Properties(t => new { t.DepartmentID, t.Administrator, t.StartDate, t.Budget }); m.ToTable("DepartmentDetails"); });
五、表拆分
兩個(gè)實(shí)體類(lèi)型映射到同一個(gè)表。
1.兩個(gè)類(lèi)必須共享同一個(gè)主鍵。
2.兩個(gè)類(lèi)之間的關(guān)系必須被映射為表之間的一對(duì)一關(guān)系。
modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorID); //共用主鍵 modelBuilder.Entity<Instructor>() .HasRequired(t => t.OfficeAssignment).WithRequiredPrincipal(t => t.Instructor);//一對(duì)一關(guān)系 modelBuilder.Entity<Instructor>().ToTable("Instructor"); modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");
六、將類(lèi)指定為復(fù)雜類(lèi)型
1、指定方法:
DataAnnotations方式:
[ConlexType] public Details details;
或FluentAPI:
modelBuilder.ComplexType<Details>();
注意:
1.復(fù)雜類(lèi)型類(lèi)不能有主鍵。
2.復(fù)雜類(lèi)型只能包含.net基礎(chǔ)類(lèi)型的屬性。
3.使用復(fù)雜類(lèi)型的類(lèi),只能包復(fù)雜類(lèi)型的一個(gè)實(shí)例,不能使用復(fù)雜類(lèi)型的集合。
2、配置復(fù)雜類(lèi)型的屬性
(1)、可以對(duì) ComplexTypeConfiguration 調(diào)用 Property。
modelBuilder.ComplexType<Details>() .Property(t => t.Location).HasMaxLength(20);
或
public class AddressComplexTypeConfiguration:ComplexTypeConfiguration<Address> { public AddressComplexTypeConfiguration() { Property(a => a.Country).HasColumnName("Country").HasMaxLength(100); Property(a => a.ZipCode).HasColumnName("ZipCode").HasMaxLength(6); } }
(2)、也可以使用點(diǎn)表示法訪問(wèn)復(fù)雜類(lèi)型的屬性。
modelBuilder.Entity<OnsiteCourse>().Property(t => t.Details.Location) .HasMaxLength(20);
七、DataBase初始化
1、調(diào)用Database.SetInitializer方法:
一般Global.ascx.cs,Main應(yīng)用程序的入口等地方調(diào)用Database.SetInitializer方法:
- 只要Fluent API配置的數(shù)據(jù)庫(kù)映射發(fā)生變化或者domain中的model發(fā)生變化了,就把以前的數(shù)據(jù)庫(kù)刪除掉,根據(jù)新的配置重新建立數(shù)據(jù)庫(kù)。
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BreakAwayContext>());
- 只有在沒(méi)有數(shù)據(jù)庫(kù)的時(shí)候才會(huì)根據(jù)數(shù)據(jù)庫(kù)連接配置創(chuàng)建新的數(shù)據(jù)庫(kù)。這種配置主要用于production環(huán)境。
Database.SetInitializer(new CreateDatabaseIfNotExists<BreakAwayContext>());
- 不管數(shù)據(jù)庫(kù)映射或者model是否發(fā)生變化,每次都重新刪除并根據(jù)配置重建數(shù)據(jù)庫(kù)。
Database.SetInitializer(new DropCreateDatabaseAlways<BreakAwayContext>());
2、通過(guò)配置文件更靈活的指定數(shù)據(jù)庫(kù)初始化的方式:
<?xml version="1.0"?> <configuration> <appSettings> <add key="DatabaseInitializerForTypeOrderSystemContext" value="System.Data.Entity.DropCreateDatabaseIfModelChanges[[OrderSystemContext]], EntityFramework" /> </appSettings> </configuration>
3、自定義數(shù)據(jù)庫(kù)初始化類(lèi)
通過(guò)自定的初始化類(lèi),還可以將一些基礎(chǔ)數(shù)據(jù)在創(chuàng)建數(shù)據(jù)庫(kù)之后插入到數(shù)據(jù)庫(kù)中去。
public class DropCreateOrderDatabaseWithSeedValueAlways : DropCreateDatabaseAlways<OrderSystemContext> { protected override void Seed(OrderSystemContext context) { context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6400", Manufactory = "DELL", ListPrice = 5600, NetPrice = 4300 }); context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6420", Manufactory = "DELL", ListPrice = 7000, NetPrice = 5400 }); } } Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());
到此這篇關(guān)于Entity Framework映射TPH、TPT、TPC與繼承類(lèi)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中winform中panel重疊無(wú)法顯示問(wèn)題的解決
這篇文章主要介紹了C#中winform中panel重疊無(wú)法顯示問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10c#數(shù)據(jù)綁定之?dāng)?shù)據(jù)轉(zhuǎn)化為信息的示例
這篇文章主要介紹了c#數(shù)據(jù)綁定中的數(shù)據(jù)轉(zhuǎn)化為信息的示例,需要的朋友可以參考下2014-04-04C#程序中創(chuàng)建、復(fù)制、移動(dòng)、刪除文件或文件夾的示例
這篇文章主要介紹了C#程序中創(chuàng)建、復(fù)制、移動(dòng)、刪除文件或文件夾的示例,即對(duì)System.IO命名空間中類(lèi)的運(yùn)用,需要的朋友可以參考下2016-02-02.NET中的async和await關(guān)鍵字使用及Task異步調(diào)用實(shí)例
這篇文章主要介紹了.NET中的async和await關(guān)鍵字使用及Task異步調(diào)用實(shí)例,本文還包含了取消執(zhí)行和顯示進(jìn)度的例子,需要的朋友可以參考下2014-07-07C# Bitmap圖像處理(含增強(qiáng)對(duì)比度的三種方法)
本文主要介紹了C# Bitmap圖像處理(含增強(qiáng)對(duì)比度的三種方法),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11