有兩種方式來實現數據庫映射:html
有繼承關係的實體如何映射?git
就是把父類和子類生成同一張表,額外增長了一列Discriminator字段,區分是父類或子類的數據類型github
好比:數據庫
父類Book對象併發
public class Book { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int BookID { get; set; } public string BookName { get; set; } public int Pages { get; set; } }
子類HistoryBooks對象,繼承Bookapp
public class HistoryBooks:Book { public int Chapter { get; set; } }
數據庫生成一張表ide
無論父類子類,各自生成一張表,以及在子類中增長二者聯繫的外鍵;ui
定義TPT方式 父類和子類定義 [Table("XXX")]this
如:spa
父類
[Table("Book")] public class Book { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int BookID { get; set; } public string BookName { get; set; } public int Pages { get; set; } }
子類
[Table("HistoryBooks")] public class HistoryBooks:Book {public int Chapter { get; set; } }
映射數據生成的兩張表
Book:
HistoryBooks:
給實體對象的屬性加上註解特性,實現與數據庫之間創建映射關係並進行控制
如:
Booid映射到表中字段爲自增的主鍵
DataAnnotations 包含的經常使用特性:
KeyAttribute:對應數據庫中表的主鍵的設置
RequiredAttribute:對應數據庫中字段的數據不可null
MaxLengthAttribute:對應數據庫中字符串類型字段的最大長度
ConcurrencyCheckAttribute:指定用於開放式併發檢查的列的數據類型
TimestampAttribute:將列的數據類型指定爲行版本
DatabaseGeneratedAttribute:標記指定實體屬性是由數據庫生成的,並指定生成策略(None數據庫不生成值,Identity當插入行時,數據庫生成值,Computed當插入或更新行時,數據庫生成值)
TableAttribute:指定實體類對應的數據表名
ColumnAttribute:指定實體屬性在數據庫中的列名
ForeignKeyAttribute :指定導航屬性的外鍵字段
NotMappeAttribute:不映射對應字段
Fluent API的配置方式能夠將實體類與映射配置進行解耦合
有兩種方式來實現Fluent API的映射配置
以下面的Book類,再也不有Data Annotation特性
public class Book { public int BookID { get; set; } public string BookName { get; set; } public int Pages { get; set; } }
重寫Dbcontext中的OnModelCreating方法實現Book類映射的配置:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Book>().HasKey(t => t.BookID); base.OnModelCreating(modelBuilder); }
現實項目中,實體對象多是很是多的,在OnModelCreating方法中逐一進行映射配置,可想而知會形成Dbcontext的代碼龐大。
一、在新建的BookMap類實現映射配置
public class BookMap : EntityTypeConfiguration<Book> { public BookMap() { this.ToTable("Book", "dbo"); this.HasKey(p => p.BookID); //this.HasKey(p => new { p.BookID, p.BookPreID });//關聯主鍵 this.Property(p => p.BookID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);//自動生成 this.Property(p => p.BookName).IsRequired().HasMaxLength(20).HasColumnName("BookName").IsUnicode(false);//非空,最大長度20,自定義列名,列類型爲varchar而非nvarchar this.Ignore(p => p.BookDescription);//忽略改屬性的映射 } }
二、依舊重寫Dbcontext中的OnModelCreating方法,將BookMap 類的實例添加到modelBuilder的Configurations。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new BookMap()); }
這樣能大大減小OnModelCreating的代碼量,依然存在一個問題,就是實體對象一多,仍是要逐條將Map類的實例添加到modelBuilder的Configurations
三、利用反射將程序集中全部的EntityTypeConfiguration添加到modelBuilder.Configurations中,能夠說徹底解耦了
protected override void OnModelCreating(DbModelBuilder modelBuilder) { var typesToRegister = Assembly.GetExecutingAssembly().GetTypes() .Where(type => !String.IsNullOrEmpty(type.Namespace)) .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)); foreach (var type in typesToRegister) { dynamic configurationInstance = Activator.CreateInstance(type); modelBuilder.Configurations.Add(configurationInstance); } }
注:此段代碼源自網友文章,摘自nopCommerce項目的代碼 鏈接