如何使用 abp 创建 module 并应用单独的数据库迁移
最近在學(xué)習(xí)使用 abp 來做一些小程序。abp 是一個功能豐富的 .NET 開發(fā)框架,完全開源,遵循 DDD(領(lǐng)域驅(qū)動)設(shè)計模式,支持微服務(wù)開發(fā),集成了 Identity、角色權(quán)限、本地化、動態(tài)代理、后臺任務(wù)、分布式消息、審計日志、多租戶支持等多個組件和特性,并提供了 Blazor 和 Angular 的前臺頁面。基于此框架可以遵循最佳實(shí)踐,省去自己開發(fā)腳手架的時間,提升開發(fā)效率。但因為 abp 封裝了非常多的功能,有時候需要花時間研究其配置,才能更好地發(fā)揮效能。
abp 的一個優(yōu)勢是模塊化,可以在框架基礎(chǔ)上開發(fā)出一個個的 module,以方便重用。國內(nèi) .NET 社區(qū)里已經(jīng)開發(fā)出了非常多的模塊,官方也提供了集成了很多模塊的商業(yè)版。對我來說,使用模塊解決的一個問題是,abp 升級非常頻繁,如果將我的業(yè)務(wù)系統(tǒng)做成模塊,能夠更好的與框架本身進(jìn)行隔離,這樣以后框架升級的時候就無需擔(dān)心對業(yè)務(wù)系統(tǒng)有破壞性的更改。本文介紹了如何開發(fā)一個模塊,并使用單獨(dú)的數(shù)據(jù)庫及實(shí)現(xiàn)遷移。
創(chuàng)建 abp 項目
官方文檔已經(jīng)提供了非常詳細(xì)的新建項目向?qū)А⒖?#xff1a;https://docs.abp.io/en/abp/latest/Getting-Started-Create-Solution?UI=Blazor&DB=EF&Tiered=Yes
CLI 命令參考:https://docs.abp.io/en/abp/latest/CLI
我們使用 abp CLI 創(chuàng)建一個新項目。我使用 Blazor 來開發(fā)前端頁面,正好學(xué)一下。
abp?new?MainApp?-u?blazor然后按照官方文檔操作即可:https://docs.abp.io/en/abp/latest/Getting-Started-Running-Solution?UI=Blazor&DB=EF&Tiered=Yes
主要步驟是:
修改數(shù)據(jù)庫連接字符串
運(yùn)行 .DbMigrator 項目初始化數(shù)據(jù)庫并填充初始數(shù)據(jù)。
運(yùn)行 .HttpApi.Host ?項目
如果操作正確,我們應(yīng)該能夠看到 Swagger 文檔了。
如果同時啟動 .HttpApi.Host 和 .Blazor 項目,前端頁面也應(yīng)該可以正常展示。基本的用戶登錄、角色權(quán)限都有了。
創(chuàng)建一個新模塊
剛開始我是用 CLI 創(chuàng)建了一個新模塊,然后手動把兩個項目的 solution 文件集成到一塊,麻煩而且易出錯。后來發(fā)現(xiàn)原來 CLI 已經(jīng)提供了將新模塊添加到現(xiàn)有解決方案的命令,可參考:https://docs.abp.io/en/abp/latest/CLI#options-3
可以使用以下的命令:
abp?add-module?MyModule?--new?--add-to-solution-file注意運(yùn)行該命令的時候要在 MainApp 的目錄下。這樣 CLI 會在當(dāng)前目錄下創(chuàng)建一個 modules 目錄來存放新模塊的解決方案,同時把所有項目添加到 MainApp 的解決方案中,還會修改一些文件,這樣我們就不用手動集成模塊了。
添加新 Model
接下來繼續(xù)按照官方文檔來添加新的 Model:https://docs.abp.io/en/abp/latest/Tutorials/Part-1
具體內(nèi)容這里就不展開了,可根據(jù)實(shí)際需要添加幾個 Model。
步驟大概是:
添加 Model
更新模塊 MyModule.EntityFrameworkCore 項目中的 MyModuleDbContext.cs 文件,添加相應(yīng)的 DbSet
在 MyModuleDbContextModelCreatingExtensions.cs 中添加模型映射
為模塊準(zhǔn)備數(shù)據(jù)庫遷移
接下來就是本文的重點(diǎn),如何為模塊添加一個單獨(dú)的數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)庫遷移。
首先在 MainApp.EntityFrameworkCore 項目中添加目錄 EntityFrameworkCore\MyModule。在這個目錄中創(chuàng)建一個名為 MyModuleMigrationsDbContext.cs 的文件。內(nèi)容如下:
public?class?MyModuleMigrationsDbContext?:?AbpDbContext<MyModuleMigrationsDbContext>{public?MyModuleMigrationsDbContext(DbContextOptions<MyModuleMigrationsDbContext>?options)?:?base(options){}protected?override?void?OnModelCreating(ModelBuilder?modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ConfigureMyModule();}}然后添加一個名為 MyModuleMigrationsDbContextFactory.cs 的文件:
public?class?MyModuleMigrationsDbContextFactory?:?IDesignTimeDbContextFactory<MyModuleMigrationsDbContext>{public?MyModuleMigrationsDbContext?CreateDbContext(string[]?args){var?configuration?=?BuildConfiguration();var?builder?=?new?DbContextOptionsBuilder<MyModuleMigrationsDbContext>().UseSqlServer(configuration.GetConnectionString("MyModule"));return?new?MyModuleMigrationsDbContext(builder.Options);}private?static?IConfigurationRoot?BuildConfiguration(){var?builder?=?new?ConfigurationBuilder().SetBasePath(Path.Combine(Directory.GetCurrentDirectory(),?"../MainApp.DbMigrator/")).AddJsonFile("appsettings.json",?optional:?false);return?builder.Build();}}這兩個文件與 MainApp 的 DbContext 內(nèi)容是類似的,大家可以比較一下。因為模塊也要從 appsettings.json 中讀取數(shù)據(jù)庫配置,因此我們需要修改 appsettings.json 中的數(shù)據(jù)庫鏈接字符串,注意需要修改兩個位置:一個是 MainApp.DbMigrator 項目中的,另一個是 MainApp.HttpApi.Host 項目中的。仿照 MainApp 的連接字符串添加一個名為 MyModule 的即可。這樣模塊就可以有一個單獨(dú)的數(shù)據(jù)庫了。
運(yùn)行模塊數(shù)據(jù)庫遷移
創(chuàng)建了新的 Model 后,我們要對數(shù)據(jù)進(jìn)行遷移,以應(yīng)用這些更改。
將 terminal 導(dǎo)航到 MainApp.EntityFrameworkCore 目錄,運(yùn)行以下命令:
dotnet?ef?migrations?add?migrationName?--context?MyModuleMigrationsDbContext?--output-dir?Migrations/MyModule注意要指定要遷移的 DbContext,也就是 MyModuleMigrationsDbContext。同時我們還將遷移文件放在 Migrations/MyModule 目錄下,這樣不會與 MainApp 的遷移文件混淆。
如果一切正常,我們就可以在指定目錄下看到生成的遷移文件了。
運(yùn)行以下命令以應(yīng)用數(shù)據(jù)庫遷移:
dotnet?ef?database?update?--context?MyModuleMigrationsDbContext這樣模塊的數(shù)據(jù)庫遷移就完成了。
其他設(shè)置
接下來按照官方文檔繼續(xù)添加相應(yīng)的 AppService 及其接口等。這樣我們的模塊已經(jīng)與 MainApp 是隔離的了,包括 Blazor 頁面也是在一個單獨(dú)的項目里。
如果運(yùn)行 .HttpApi.Host 沒有看到模塊的 API,可以檢查下 MainApp.HttpApi.Host 項目中的 MainAppHttpApiHostModule.cs 文件,看是否配置正確:
private?void?ConfigureConventionalControllers(){Configure<AbpAspNetCoreMvcOptions>(options?=>{options.ConventionalControllers.Create(typeof(MainAppApplicationModule).Assembly);//?Add?the?below?lineoptions.ConventionalControllers.Create(typeof(MyModuleApplicationModule).Assembly);});}再次運(yùn)行 .HttpApi.Host 和 .Blazor 項目,可以看到前端頁面已經(jīng)添加了一個新模塊的鏈接,只是內(nèi)容頁是空的。接下來我們就可以在 MyModule 解決方案里的 Blazor 項目中開發(fā)前端頁面了。
在添加 Model 后我還遇到過一個錯誤,如下圖所示:
Autofact.Core.DependencyResolutionException: 'An exception was thrown while activating Volo.Abp.IdentityServer.Grants.PersistedGrantStore ....'
乍一看還以為是 IdentityServer 的問題,其實(shí)不是。展開看 inner exception 就會發(fā)現(xiàn)這個是我們添加的 Dto 的 mapping 導(dǎo)致的。因為 Entity 是有 Id 的,但 CreateUpdateProductDto 沒有Id,所以 mapping 出錯了。如果遇到這種情況,可以將 Id 省略掉:
CreateMap<CreateUpdateProductDto,?Product>().Ignore(x?=>?x.Id);學(xué)習(xí)了幾天感覺這個框架還是挺方便的,功能非常強(qiáng)大,但學(xué)習(xí)起來還是有一定難度的??蚣芨鞑糠种g的依賴非常多,如果不仔細(xì)研究,很容易處處碰壁。好在官方文檔寫的還是相對比較詳細(xì)的,只是部分文檔還有空缺。希望官方以后補(bǔ)足吧。是否使用框架開發(fā)是一個兩難的問題,太依賴框架可能會失去對細(xì)節(jié)的把控,處處受制于框架的實(shí)現(xiàn);不使用框架就得自己重復(fù)造輪子。只能見仁見智了。
萬水千山總是情,點(diǎn)個關(guān)注行不行
天若有情天亦老,加個粉絲好不好
總結(jié)
以上是生活随笔為你收集整理的如何使用 abp 创建 module 并应用单独的数据库迁移的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宇宙最強的IDE - Visual St
- 下一篇: SignalR的使用