一. 前言
①: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. 業務模擬
①. 用戶基本信息和角色基本信息,不做關聯
②. 用戶信息增加了或者刪除
③. 角色信息刪除了或者增加
二. 使用步驟
1. 新建【Ypf.Service】類庫和【Ypf.Test】控制台項目,並分別通過Nuget安裝EF程序集。
2. 在【Ypf.Service】類庫中新建“UserInfor”、“RoleInfor”實體類,“UserInforConfig”、“RoleInforConfig”實體類對應的隔離出來的表的配置文件。
PS:這里為了方便管理,一張表對應一個EF的配置類文件,比全部直接寫在 OnModelCreating 方法中更清晰。
分享實體類代碼:
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 }
分享表配置文件代碼:
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:配置數據遷移策略固然可以解決該問題,但我們這里用一種比較笨的方法,關閉數據庫初始化策略,然后手動配置代碼和修改數據庫字段進行對應即可。
分享關閉數據庫初始化策略的代碼:
手動修改數據庫和代碼實體中的屬性對應后重新運行代碼,運行成功。
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。