一. 前言html
①:EF的三種模式(四) 之 原生正宗的 CodeFirst模式的默認約定
②:EF的CodeFirst模式經過DataAnnotations修改默認協定
③:EF的CodeFirst模式經過Fluent API修改默認協定
④:EF的CodeFirst模式的四種初始化策略和經過Migration進行數據的遷移數據庫
2. 框架模式
這裏不採用傳統的三層架構(DAL、BLL),而是使用:Ypf.DTO、Ypf.Service、Ypf.IService、Ypf.Utils、Ypf.Web 這種劃分模式,本節爲了方便測試,僅僅使用 Ypf.Service 和 Ypf.Test(控制檯)兩個框架進行測試。架構
3. 業務模擬
①. 用戶基本信息和角色基本信息,不作關聯
②. 用戶信息增長了或者刪除
③. 角色信息刪除了或者增長框架
二. 使用步驟ide
1. 新建【Ypf.Service】類庫和【Ypf.Test】控制檯項目,並分別經過Nuget安裝EF程序集。函數
2. 在【Ypf.Service】類庫中新建「UserInfor」、「RoleInfor」實體類,「UserInforConfig」、「RoleInforConfig」實體類對應的隔離出來的表的配置文件。測試
PS:這裏爲了方便管理,一張表對應一個EF的配置類文件,比所有直接寫在 OnModelCreating 方法中更清晰。ui
分享實體類代碼:this
1 /// <summary> 2 /// 用戶表 3 /// </summary> 4 public class UserInfor 5 { 6 public string id { get; set; } 8 public string userName { get; set; } 10 public int userAge { get; set; } 11 14 } 15 /// <summary> 16 /// 角色信息 17 /// </summary> 18 public class RoleInfor 19 { 20 public string id { get; set; } 22 public string roleName { get; set; } 24 public int roleAge { get; set; } 25 }
分享表配置文件代碼:spa
1 /// <summary> 2 /// UserInfor實體對應表的配置 3 /// </summary> 4 class UserInforConfig :EntityTypeConfiguration<UserInfor> 5 { 6 public UserInforConfig() 7 { 8 this.ToTable("T_UserInfor"); 9 this.HasKey<string>(u => u.id).Property(u => u.id).HasColumnType("varchar").HasMaxLength(32); 10 this.Property(u => u.userName).HasColumnType("varchar").HasMaxLength(50); 11 this.Property(u => u.userAge).HasColumnType("int").IsRequired(); 12 } 13 } 14 /// <summary> 15 /// RoleInfor實體對應表的配置 16 /// </summary> 17 class RoleInforConfig : EntityTypeConfiguration<RoleInfor> 18 { 19 public RoleInforConfig() 20 { 21 this.ToTable("T_RoleInfor"); 22 this.HasKey<string>(u => u.id).Property(u => u.id).HasColumnType("varchar").HasMaxLength(32); 23 this.Property(u => u.roleName).HasColumnType("varchar").HasMaxLength(50); 24 this.Property(u => u.roleAge).HasColumnType("int").IsRequired(); 25 } 26 }
3. 在【Ypf.Service】類庫中新建EF上下文 「YpfContext」類,使用EF的默認初始化策略(DB不存在則建立,實體不對應則報錯) ,而後override OnModelCreating方法,並經過反射一次性加載EF的全部Fluent Api配置,最後聲明要映射的實體。
分享EF上下文的代碼
public class YpfContext:DbContext { /// <summary> /// 繼承父類構造函數,ypfConnectionString表明配置文件中鏈接字符串的名字 /// </summary> public YpfContext():base("name=ypfConnectionString") { } /// <summary> /// OnModelCreating方法重寫,FluentAPI對錶的配置都是在該方法中,可是當表數量多的話 /// 該方法內部就會顯得特別亂,因此咱們這裏採用分離的方式,一張表對應一個配置文件類, /// 最後所有註冊到該方法中便可 /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //1. 分開註冊 //modelBuilder.Configurations.Add(new UserInforConfig()); //modelBuilder.Configurations.Add(new RoleInforConfig()); //2. 一次性加載全部Fluent API的配置 modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); } public DbSet<UserInfor> UserInfor { get; set; } public DbSet<RoleInfor> RoleInfor { get; set; } }
4. 給【Ypf.Test】配置數據庫鏈接字符串,而且進行一個簡單的數據庫查詢操做,會發如今SQLServer默認目錄生成一個名爲「FrameFluentApiDB」的數據庫,且表、字段對應均正確。
分享數據庫鏈接字符串代碼:
1 <connectionStrings> 2 <add name="ypfConnectionString" connectionString="Data Source=localhost;Initial Catalog=FrameFluentApiDB;User ID=sa;Password=123456" providerName="System.Data.SqlClient" /> 3 </connectionStrings>
分享簡單的數據庫查詢代碼:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 using (YpfContext db=new YpfContext()) 6 { 7 var list = db.UserInfor.ToList(); 8 9 Console.WriteLine("建立成功"); 10 Console.ReadKey(); 11 } 12 } 13 }
運行後生成的數據庫:
5. 給UserInfor實體增長一個「userSex」屬性,並在UserInforConfig文件中對該屬性進行配置,以下圖,再次運行代碼,報錯,提示上下文發生改變,請走數據遷移。
修改後代碼:
報錯提示:
PS:配置數據遷移策略當然能夠解決該問題,但咱們這裏用一種比較笨的方法,關閉數據庫初始化策略,而後手動配置代碼和修改數據庫字段進行對應便可。
分享關閉數據庫初始化策略的代碼:
手動修改數據庫和代碼實體中的屬性對應後從新運行代碼,運行成功。
!