最近在学习使用 abp 来做一些小程序。abp 是一个功能丰富的 .NET 开发框架,完全开源,遵循 DDD(领域驱动)设计模式,支持微服务开发,集成了 Identity、角色权限、本地化、动态代理、后台任务、分布式消息、审计日志、多租户支持等多个组件和特性,并提供了 Blazor 和 Angular 的前台页面。基于此框架可以遵循最佳实践,省去自己开发脚手架的时间,提升开发效率。但因为 abp 封装了非常多的功能,有时候需要花时间研究其配置,才能更好地发挥效能。

abp 的一个优势是模块化,可以在框架基础上开发出一个个的 module,以方便重用。国内 .NET 社区里已经开发出了非常多的模块,官方也提供了集成了很多模块的商业版。对我来说,使用模块解决的一个问题是,abp 升级非常频繁,如果将我的业务系统做成模块,能够更好的与框架本身进行隔离,这样以后框架升级的时候就无需担心对业务系统有破坏性的更改。本文介绍了如何开发一个模块,并使用单独的数据库及实现迁移。

创建 abp 项目

官方文档已经提供了非常详细的新建项目向导。参考: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 创建一个新项目。我使用 Blazor 来开发前端页面,正好学一下。

abp new MainApp -u blazor

然后按照官方文档操作即可:https://docs.abp.io/en/abp/latest/Getting-Started-Running-Solution?UI=Blazor&DB=EF&Tiered=Yes

主要步骤是:

  • 修改数据库连接字符串

  • 运行 .DbMigrator 项目初始化数据库并填充初始数据。

  • 运行 .HttpApi.Host  项目

如果操作正确,我们应该能够看到 Swagger 文档了。

如果同时启动 .HttpApi.Host.Blazor 项目,前端页面也应该可以正常展示。基本的用户登录、角色权限都有了。

创建一个新模块

刚开始我是用 CLI 创建了一个新模块,然后手动把两个项目的 solution 文件集成到一块,麻烦而且易出错。后来发现原来 CLI 已经提供了将新模块添加到现有解决方案的命令,可参考:https://docs.abp.io/en/abp/latest/CLI#options-3

可以使用以下的命令:

abp add-module MyModule --new --add-to-solution-file

注意运行该命令的时候要在 MainApp 的目录下。这样 CLI 会在当前目录下创建一个 modules 目录来存放新模块的解决方案,同时把所有项目添加到 MainApp 的解决方案中,还会修改一些文件,这样我们就不用手动集成模块了。

添加新 Model

接下来继续按照官方文档来添加新的 Model:https://docs.abp.io/en/abp/latest/Tutorials/Part-1

具体内容这里就不展开了,可根据实际需要添加几个 Model。

步骤大概是:

  • 添加 Model

  • 更新模块 MyModule.EntityFrameworkCore 项目中的 MyModuleDbContext.cs 文件,添加相应的 DbSet

  • MyModuleDbContextModelCreatingExtensions.cs 中添加模型映射

为模块准备数据库迁移

接下来就是本文的重点,如何为模块添加一个单独的数据库并实现数据库迁移。

首先在 MainApp.EntityFrameworkCore 项目中添加目录 EntityFrameworkCore\MyModule。在这个目录中创建一个名为 MyModuleMigrationsDbContext.cs 的文件。内容如下:

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 内容是类似的,大家可以比较一下。因为模块也要从 appsettings.json 中读取数据库配置,因此我们需要修改 appsettings.json 中的数据库链接字符串,注意需要修改两个位置:一个是 MainApp.DbMigrator 项目中的,另一个是 MainApp.HttpApi.Host 项目中的。仿照 MainApp 的连接字符串添加一个名为 MyModule 的即可。这样模块就可以有一个单独的数据库了。

运行模块数据库迁移

创建了新的 Model 后,我们要对数据进行迁移,以应用这些更改。

将 terminal 导航到 MainApp.EntityFrameworkCore 目录,运行以下命令:

dotnet ef migrations add migrationName --context MyModuleMigrationsDbContext --output-dir Migrations/MyModule

注意要指定要迁移的 DbContext,也就是 MyModuleMigrationsDbContext。同时我们还将迁移文件放在 Migrations/MyModule 目录下,这样不会与 MainApp 的迁移文件混淆。

如果一切正常,我们就可以在指定目录下看到生成的迁移文件了。

运行以下命令以应用数据库迁移:

dotnet ef database update --context MyModuleMigrationsDbContext

这样模块的数据库迁移就完成了。

其他设置

接下来按照官方文档继续添加相应的 AppService 及其接口等。这样我们的模块已经与 MainApp 是隔离的了,包括 Blazor 页面也是在一个单独的项目里。

如果运行 .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);});}

再次运行 .HttpApi.Host.Blazor 项目,可以看到前端页面已经添加了一个新模块的链接,只是内容页是空的。接下来我们就可以在 MyModule 解决方案里的 Blazor 项目中开发前端页面了。

在添加 Model 后我还遇到过一个错误,如下图所示:

Autofact.Core.DependencyResolutionException: 'An exception was thrown while activating Volo.Abp.IdentityServer.Grants.PersistedGrantStore ....'

乍一看还以为是 IdentityServer 的问题,其实不是。展开看 inner exception 就会发现这个是我们添加的 Dto 的 mapping 导致的。因为 Entity 是有 Id 的,但 CreateUpdateProductDto 没有Id,所以 mapping 出错了。如果遇到这种情况,可以将 Id 省略掉:

CreateMap<CreateUpdateProductDto, Product>().Ignore(x => x.Id);

学习了几天感觉这个框架还是挺方便的,功能非常强大,但学习起来还是有一定难度的。框架各部分之间的依赖非常多,如果不仔细研究,很容易处处碰壁。好在官方文档写的还是相对比较详细的,只是部分文档还有空缺。希望官方以后补足吧。是否使用框架开发是一个两难的问题,太依赖框架可能会失去对细节的把控,处处受制于框架的实现;不使用框架就得自己重复造轮子。只能见仁见智了。

万水千山总是情,点个关注行不行

天若有情天亦老,加个粉丝好不好

如何使用 abp 创建 module 并应用单独的数据库迁移相关推荐

  1. Django项目的创建、Admin后台系统以及数据库迁移

    PyCharm新建一个Django项目: 新建项目  ->  Django项目 -> 选择创建位置.项目名.应用名(应用名与项目名不能相同) -> 选择创建Create 创建项目后, ...

  2. 【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )

    文章目录 一.Page Ability 的 action 标识 二.Page Ability 之间的界面跳转及传递数据 三.鸿蒙工程下创建 Module 四.代码示例 五.执行效果 参考文档 : Pa ...

  3. python如何创建问答窗口_在tkin中创建一个新的单独窗口

    我想创建一个新的单独窗口,比如在记事本中打开一个新页面.在 我写的是:import tinter from tkinter import Tk, Frame, Menu class Example(F ...

  4. idea 创建module 没有src

    在使用spring-framework-4.2.x 创建module,生成gradle项目,都没有生成src的内容,只有孤零零的gradle文件 可能的原因之一:   网络的问题 处理: 1,检测网络 ...

  5. 【Android 插件化】VirtualApp 接入 ( 在 VirtualApp 工程下创建 Module | 添加依赖 | 启动 VirtualApp 插件引擎 )

    文章目录 一.在 VirtualApp 工程下创建 Module 二.添加依赖 三.启动 VirtualApp 插件引擎 四.博客源码 一.在 VirtualApp 工程下创建 Module 在 [A ...

  6. abp mysql .net core_ABP .Net Core Entity Framework迁移使用MySql数据库

    一.迁移说明 ABP模板项目Entity Framework Core默认使用的是Sql Server,也很容易将数据库迁移到MySQL,步骤如下. 二.迁移MySQL步骤 1. 下载项目 请到 ht ...

  7. oracle数据库迁移 增大空间,Oracle数据库迁移、创建表空间、创建数据表实例讲解-Oracle...

    数据库迁移 对于数据库迁移来说,如果源数据库与目标数据库版本一致,推荐使用Oracle导入或者pl/sql导入:如果版本不一致,则可以使用sql导入的方式. 创建表空间 create tablespa ...

  8. 数据库创建存储过程_创建存储过程来修复孤立的数据库用户

    数据库创建存储过程 问题 ( The Problem ) This problem demonstrates a very common scenario. When a backed up data ...

  9. centos shell mysql数据库备份_CentOS6.5下通过Shell创建、备份、还原MySQL数据库

    CentOS6.5下通过Shell创建.备份.还原MySQL数据库 创建数据库: mysql -uroot -p123456 -e "CREATE DATABASE IF NOT EXIST ...

最新文章

  1. Linux定时程序没有之行完,如何在linux上定时执行程序
  2. 【javascript 动态添加数据到 HTML 页面】
  3. VS 2017 安装测试
  4. TeeChart中 Line的Clear方法
  5. 复制Excel分类汇总结果的三种方法
  6. [Java基础]反射案列
  7. 前端学习(3033):vue+element今日头条管理-反馈
  8. [转载] 2020最新Java面试题,常见面试题及答案汇总
  9. flask-limiter限制单个IP访问的频率和次数
  10. 嵌入式操作系统内核原理和开发(线程切换)
  11. 通过资源名称得到资源id
  12. python全栈_010_Python3基本数据类型--元组
  13. 菜鸟的Python学习之路(流水账)
  14. PHP重置static静态变量
  15. 朋友圈文字怎么到中间_怎样查看微信朋友圈访客记录
  16. Wannacry蠕虫勒索软件“永恒之蓝”3种修复方案
  17. 杯具啊,混合语言编程的弊端出现了,兼谈js的开发工具
  18. 大野耐一的十条管理训诫|优思学院
  19. 基于标记的分水岭分割算法
  20. 【干货福利】67个拯救web开发者的工具、库和资源!——爱创课堂

热门文章

  1. three.js插件实现立体动感视频播放效果
  2. ffmpeg avformat_open_input返回失败的解决办法
  3. 监测利器cacti服务安装
  4. JMS : Java Message Service (Java消息服务)之一 [转]
  5. 八种ADSL接入情况中断流现象分析
  6. mysql Backup recovery
  7. 我的手机 不支持箭头函数
  8. 下拉刷新:继承listView控件
  9. java bean 工厂模式_深入理解Java的三种工厂模式
  10. 小程序禁用ios 左右滑动_如何在使用应用程序时禁用iOS控制中心