前一篇 第一篇:Entity Framework 簡介 我有講到,ORM 最關鍵的 Mapping,也提到了最早實現Mapping的技術,就是 特性 + 反射,那Entity Framework 實現Mapping 又是怎樣的呢? EntityFramework 實現Mapping 有兩種方式。
1. 數據注解(DataAnnotations)
2. Fluent API
一. 數據注解,這種方式,就是在實體和屬性加上一些EntityFramework 定義好的一些特性,然後EntityFramework,在具體操作數據庫時進行反射。跟我們上篇提到 特性+反射 一樣的方案。因此今天不會在這篇講 DataAnnotations 。會貼一點實例代碼。
比較要注意的是,實現 DataAnnotations ,要引用 System.ComponentModel.DataAnnotations 命名空間。
實例代碼如下,特殊說明一下,EntityFramework 支持 .Net 可為空表達法,如 int?,DateTime? 。下面代碼 最後修改時間 LastModifiedDateTime 就是這樣。
using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace EntityFrameworkSample.Models { [Table("Sample_Order")] //標示為 表名 //[Table("Sample_Order", Schema = "dbo")] //標示為 表名 ,表的擁有者 public class OrderModel { [Key]//標示為 主鍵 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 標示為 自動增量 public Guid OrderGuid { get; set; } [Required] //標示為 必填 [MaxLength(30)] //標示為 字符串長度最大30 public string OrderNo { get; set; } [Required] //標示為 必填 [MaxLength(20)] //標示為 字符串長度最大30 public string OrderCreator { get; set; } [Required] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 標示為 自動增量 數據庫有默認值 getdate() public DateTime OrderDateTime { get; set; } [Required] public string OrderStatus { get; set; } [MaxLength(1000)] public string Description { get; set; } [Required] [MaxLength(20)] //標示為 字符串長度最大30 public string Creator { get; set; } [Required] public DateTime CreateDateTime { get; set; } public string LastModifier { get; set; } public DateTime? LastModifiedDateTime { get; set; } } }
看吧,數據注解(DataAnnotations ),就是舊技術換一個叫法而已。沒有什麼大不了。其他的就靠大家去摸索了。
二 . Fluent API 查了一下百度翻譯,“流暢的API” ,我不知道這個翻譯貼不貼不切,我就以我使用Fluent API 經驗說說,Fluent API 比 數據注解好的地方。
1. 大家再看一眼上面代碼,是不是感覺有點不純淨了,本來一個干干淨淨的類,搞得亂亂的。感覺有點惡心。
2. 這一點可能要後面我貼出代碼,分享源代碼才理解,不過使用過EntityFramework Fluent API 的應該能夠理解到,配置和類分離,職責更加單一。
3. 配置和類分離,擴展性,靈活性就會更好,大家多知道,EntityFramework 不僅支持Sql Server,支持Oracle,MySql,Sqlite 等這些流行數據庫,每種產品配置也許都有細微差別,如果以 DataAnnotations 方式實作,那我豈不是要重新新增模型,一樣的表設計,為什麼要加呢? 只有配置不同才要加啊!
4. 做技術架構,這種方式封裝也比較好,怎麼好大家如果是做架構的話,兩種方式都用一下,感受一下。
廢話不多說了,直接貼出實現 Fluent API 的流程,以及代碼。
1. 創建數據庫“EntityFrameworkSample”
2. 在數據庫“EntityFrameworkSample”中,加表“Sample_Order”,然後向表中新增所需要的字段。
3. 新建解決方案 “EntityFrameworkSample”
4. 在解決方案中 新增“EntityFrameworkSample.DbContext” (配置最終使用地方),“EntityFrameworkSample.Models”(純淨數據Model),“EntityFrameworkSample.Mappings” (映射配置)三個類庫項目
5. 在“EntityFrameworkSample.DbContext” ,“EntityFrameworkSample.Mappings” 項目中,通過NuGet 安裝EntityFramework 最新版本。
6. 在 “EntityFrameworkSample.DbContext” 項目中,新增“EntityFrameworkSampleDbContext” DbContext 類,
在“EntityFrameworkSample.Models” 項目中,新增“OrderModel” Model類,
在“EntityFrameworkSample.Mappings”項目中,新增“OrderMap” 映射配置類。
三個項目 代碼圖 和引用關系如下圖
三個類的代碼分別如下
EntityFrameworkSampleDbContext
using System.Data.Entity; using EntityFrameworkSample.Mappings; using EntityFrameworkSample.Models; namespace EntityFrameworkSample.DbContext { public class EntityFrameworkSampleDbContext:System.Data.Entity.DbContext { public EntityFrameworkSampleDbContext() : base("EntityFrameworkSampleConnection") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<OrderModel>(); modelBuilder.Configurations.Add(new OrderMap()); base.OnModelCreating(modelBuilder); } } }
OrderModel
using System; namespace EntityFrameworkSample.Models { public class OrderModel { public Guid OrderGuid { get; set; } public string OrderNo { get; set; } public string OrderCreator { get; set; } public DateTime OrderDateTime { get; set; } public string OrderStatus { get; set; } public string Description { get; set; } public string Creator { get; set; } public DateTime CreateDateTime { get; set; } public string LastModifier { get; set; } public DateTime LastModifiedDateTime { get; set; } } }
OrderMap
using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using EntityFrameworkSample.Models; namespace EntityFrameworkSample.Mappings { public class OrderMap : EntityTypeConfiguration<OrderModel> { public OrderMap() { this.HasKey(m => m.OrderGuid); this.Property(m => m.OrderGuid) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(m => m.OrderNo) .IsRequired() .HasMaxLength(30); this.Property(m => m.OrderCreator) .IsRequired() .HasMaxLength(20); this.Property(m => m.OrderStatus) .IsRequired() .HasMaxLength(30); this.Property(m => m.Description) .HasMaxLength(1000); this.Property(m => m.Creator) .IsRequired() .HasMaxLength(20); this.Property(m => m.LastModifier) .HasMaxLength(15) .HasMaxLength(20); this.ToTable("Sample_Order"); this.Property(m => m.OrderGuid).HasColumnName("OrderGuid"); this.Property(m => m.OrderNo).HasColumnName("OrderNo"); this.Property(m => m.OrderCreator).HasColumnName("OrderCreator"); this.Property(m => m.OrderDateTime).HasColumnName("OrderDateTime"); this.Property(m => m.OrderStatus).HasColumnName("OrderStatus"); this.Property(m => m.Description).HasColumnName("Description"); this.Property(m => m.Creator).HasColumnName("Creator"); this.Property(m => m.CreateDateTime).HasColumnName("CreateDateTime"); this.Property(m => m.LastModifier).HasColumnName("LastModifier"); this.Property(m => m.LastModifiedDateTime).HasColumnName("LastModifiedDateTime"); } } }
至此解決方案此階段所有代碼就完成了。
大概講一下一些注意點。
1. EntityFrameworkSampleDbContext 必須要繼承 DbContext,並重寫OnModelCreating方法,來完成映射.
2. OrderMap 必須繼承EntityTypeConfiguration<>泛型類,泛型類型 OrderModel,大概告訴Map映射的是OrderModel。
好了,這篇內容結束了,不足的地方,我沒有列出Fluent API 所有api,主要是表與表的關系是如何映射的,這些希望讀者,能夠自己去摸索,篇幅有限,
還有就是DbContext 我也沒有在這篇詳細介紹,會在真正講到DbContext那篇在詳細跟大家介紹。
這篇還增加一篇續篇吧,第三篇:Entity Framework CodeFirst & Model 映射 續篇 EntityFramework Power Tools 工具使用
這篇的源代碼:http://pan.baidu.com/s/1sl89cjr