這一節我們說說數據庫遷移(Migration)。
我們之前用的DBFirst創建了實體類,但當初這么做的原因是為了節省時間。現在我們通過創建的實體類和DbContext類利用EF的Code First數據庫遷移反過來創建數據庫。ABP模板默認開啟了遷移,並且添加了一下下面的Configuration類:
1 using EntityFramework.DynamicFilters; 2 using System.Data.Entity.Migrations; 3 using Witcare.PSS.Migrations.SeedData; 4 5 namespace Witcare.PSS.Migrations 6 { 7 internal sealed class Configuration : DbMigrationsConfiguration<PSS.EntityFramework.PSSDbContext> 8 { 9 public Configuration() 10 { 11 AutomaticMigrationsEnabled = false; 12 ContextKey = "PSS"; 13 } 14 /// <summary> 15 /// 添加種子數據,比如默認管理員等數據 16 /// </summary> 17 /// <param name="context">當前數據庫上下文子類</param> 18 protected override void Seed(PSS.EntityFramework.PSSDbContext context) 19 { 20 context.DisableAllFilters(); 21 new InitialDataBuilder(context).Build(); 22 } 23 } 24 }
1 using System.Linq; 2 using Abp.Authorization; 3 using Abp.Authorization.Roles; 4 using Abp.Authorization.Users; 5 using Abp.MultiTenancy; 6 using Witcare.PSS.Authorization; 7 using Witcare.PSS.Authorization.Roles; 8 using Witcare.PSS.EntityFramework; 9 using Witcare.PSS.MultiTenancy; 10 using Witcare.PSS.Users; 11 using Microsoft.AspNet.Identity; 12 13 namespace Witcare.PSS.Migrations.SeedData 14 { 15 public class DefaultTenantRoleAndUserBuilder 16 { 17 private readonly PSSDbContext _context; 18 19 public DefaultTenantRoleAndUserBuilder(PSSDbContext context) 20 { 21 _context = context; 22 } 23 24 public void Build() 25 { 26 CreateUserAndRoles(); 27 } 28 29 private void CreateUserAndRoles() 30 { 31 //Admin role for host 32 33 var adminRoleForHost = _context.Roles.FirstOrDefault(r => r.TenantId == null && r.Name == StaticRoleNames.Host.Admin); 34 if (adminRoleForHost == null) 35 { 36 adminRoleForHost = _context.Roles.Add(new Role { Name = StaticRoleNames.Host.Admin, DisplayName = StaticRoleNames.Host.Admin, IsStatic = true }); 37 _context.SaveChanges(); 38 39 //Grant all tenant permissions 40 var permissions = PermissionFinder 41 .GetAllPermissions(new PSSAuthorizationProvider()) 42 .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Host)) 43 .ToList(); 44 45 foreach (var permission in permissions) 46 { 47 if (!permission.IsGrantedByDefault) 48 { 49 _context.Permissions.Add( 50 new RolePermissionSetting 51 { 52 Name = permission.Name, 53 IsGranted = true, 54 RoleId = adminRoleForHost.Id 55 }); 56 } 57 } 58 59 _context.SaveChanges(); 60 } 61 62 //Admin user for tenancy host 63 64 var adminUserForHost = _context.Users.FirstOrDefault(u => u.TenantId == null && u.UserName == User.AdminUserName); 65 if (adminUserForHost == null) 66 { 67 adminUserForHost = _context.Users.Add( 68 new User 69 { 70 TenantId = null, 71 UserName = User.AdminUserName, 72 Name = "System", 73 Surname = "Administrator", 74 EmailAddress = "admin@aspnetboilerplate.com", 75 IsEmailConfirmed = true, 76 Password = new PasswordHasher().HashPassword(User.DefaultPassword) 77 }); 78 79 _context.SaveChanges(); 80 81 _context.UserRoles.Add(new UserRole(adminUserForHost.Id, adminRoleForHost.Id)); 82 83 _context.SaveChanges(); 84 } 85 86 //Default tenant 87 88 var defaultTenant = _context.Tenants.FirstOrDefault(t => t.TenancyName == "Default"); 89 if (defaultTenant == null) 90 { 91 defaultTenant = _context.Tenants.Add(new Tenant { TenancyName = "Default", Name = "Default" }); 92 _context.SaveChanges(); 93 } 94 95 //Admin role for 'Default' tenant 96 97 var adminRoleForDefaultTenant = _context.Roles.FirstOrDefault(r => r.TenantId == defaultTenant.Id && r.Name == StaticRoleNames.Tenants.Admin); 98 if (adminRoleForDefaultTenant == null) 99 { 100 adminRoleForDefaultTenant = _context.Roles.Add(new Role { TenantId = defaultTenant.Id, Name = StaticRoleNames.Tenants.Admin, DisplayName = StaticRoleNames.Tenants.Admin, IsStatic = true }); 101 _context.SaveChanges(); 102 103 //Grant all tenant permissions 104 var permissions = PermissionFinder 105 .GetAllPermissions(new PSSAuthorizationProvider()) 106 .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Tenant)) 107 .ToList(); 108 109 foreach (var permission in permissions) 110 { 111 if (!permission.IsGrantedByDefault) 112 { 113 _context.Permissions.Add( 114 new RolePermissionSetting 115 { 116 Name = permission.Name, 117 IsGranted = true, 118 RoleId = adminRoleForDefaultTenant.Id 119 }); 120 } 121 } 122 123 _context.SaveChanges(); 124 } 125 126 //Admin for 'Default' tenant 127 128 var adminUserForDefaultTenant = _context.Users.FirstOrDefault(u => u.TenantId == defaultTenant.Id && u.UserName == User.AdminUserName); 129 if (adminUserForDefaultTenant == null) 130 { 131 adminUserForDefaultTenant = _context.Users.Add( 132 new User 133 { 134 TenantId = defaultTenant.Id, 135 UserName = User.AdminUserName, 136 Name = "System", 137 Surname = "Administrator", 138 EmailAddress = "admin@aspnetboilerplate.com", 139 IsEmailConfirmed = true, 140 Password = new PasswordHasher().HashPassword(User.DefaultPassword) 141 }); 142 _context.SaveChanges(); 143 144 _context.UserRoles.Add(new UserRole(adminUserForDefaultTenant.Id, adminRoleForDefaultTenant.Id)); 145 _context.SaveChanges(); 146 } 147 } 148 } 149 }
在Seed方法中,添加了租戶,角色和用戶數據。現在,我來創建初始化遷移。打開包管理器控制台,輸入下面的命令:
此處特別注意,紅色方框中一定不要忘了選擇EF項目,否則不會有下面出現的命令“Add-Migration”,”InitialData”是生成文件的后綴名(也是文件中類的名字),也可以取其他名字。
可以看到生成的文件一個以cs結尾,這里面的代碼是創建數據庫中表的,另一個以Designer.cs結尾,記錄的是數據庫遷移的版本記錄,最后一個以.resx文件是資源文件,暫且不需要考慮。
剛才我們只是創建了創建數據庫所需要的類,但還沒有創建數據庫。為了創建數據庫,需要在包管理控制台執行以下命令:
PM> Update-Database 這邊要記得:一定要把web設為啟動項目
該命令完成了這次數據庫的遷移,創建了數據庫並填充了種子數據。
當我們改變實體類時,可以使用Add-Migration命令創建新的遷移類和Update-Database命令更新數據庫。
至此,數據庫遷移完成。下一次我們說說《定義倉儲》。