配置数据库表前缀

ABP踩坑记录-目录

本篇其实和ABP关系并不大,主要是EF Core的一些应用-.-。

起因

支持数据库表前缀应该是很多应用中比较常见的功能,而在ABP中并没直接提供这一功能,所以在我们的应用中,我们转而借助EF Core的配置来实现数据库表前缀的配置。

解决方案

这里我结合了Fluent API和数据注解的形式进行配置。

首先,约定所有自定义的表,在其实体类型上都标注了[Table("tablename")]属性。

然后在QincaiDbContext中重载OnModelCreating方法。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityTypes = modelBuilder.Model.GetEntityTypes().ToList();
// 设置自定义表前缀
foreach (var entityType in entityTypes)
{
if (entityType.ClrType
.GetCustomAttributes(typeof(TableAttribute), true)
.FirstOrDefault() is TableAttribute table)
{
// 如果你的表名就是实体类型名的话,可以修改为如下形式,就不必给出[table]的Name参数
// string tableName = tablePrefix + entityType.ClrType.Name;
// 如若有其他需求也可在此进行修改
string tableName = tablePrefix + table.Name;
modelBuilder.Entity(entityType.ClrType)
.ToTable(tableName);
}
}
// 设置内置表前缀
modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>(tablePrefix);
}

经历

因为采用的Module Zero模板,其数据库上下文中已包含部分内置表,ABP Module Zero也提供了拓展方法ModelBuilder.ChangeAbpTablePrefix<TTenant, TRole, TUser>以便于修改表前缀,其默认的表前缀为Abp

剩下就是配置我们自己定义的表的前缀,这里我们考虑将表前缀以字符串常量的形式储存。

参考资料:EF Core文档

如果你喜欢用Fluent API来配置数据库,那么解决方案就很简单了,直接拼接字符串生成新表名即可。

可以参考以下代码:

// 这里tablePrefix为字符串常量
modelBuilder.Entity<Blog>().ToTable(tablePrefix + "Blogs");

但是,如果每一个类型都需要配置的话,不免显得有些冗长。因此,我便考虑通过反射的方式来统一配置表前缀。

首先,我们需要获取到所有的实体类型。

// 这里需要注意需要将迭代对象作临时存储
// 直接foreach的话会报错,即不能修改迭代中的对象
var entityTypes = modelBuilder.Model.GetEntityTypes().ToList(); foreach (var entityType in entityTypes)
{
// 配置表前缀
// ...
}

然后便是表前缀的配置,一开始我的想法是直接通过实体类型名来配置表名,但在考虑实际情况后,我认为还是需要有一定的灵活度使得该解决方案更通用。

最终,这里我选择用数据注解的方式来为指定表名,即利用[Table]特性。

因为,这是EF Core官方所提供配置方式之一,不会让大家因为配置表前缀而增删过多代码。

我们会用到[Table]特性的Name参数,例如这样:

using System.ComponentModel.DataAnnotations.Schema;

[Table("blogs")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}

因为特性并不支持在其参数中引用字符串常量,所以[Table($"{tablePrefix}blogs")]这种写法是不存在的,大家清醒一下。

然后,就是使用Fluent API来配置表前缀了。

// 通过反射获取该实体类上定义的TableAttribute
// 这里没有处理table为null的情况
TableAttribute table = (TableAttribute)entityType.ClrType
.GetCustomAttributes(typeof(TableAttribute), true)
.FirstOrDefault(); // 利用TableAttribute中的Name参数来配置表名
modelBuilder.Entity(entityType.ClrType)
.ToTable(tablePrefix + table.Name);

结合模式匹配语法,我们可以写出如下形式:

// 若table为null,模式匹配结果将为false
if (entityType.ClrType
.GetCustomAttributes(typeof(TableAttribute), true)
.FirstOrDefault() is TableAttribute table)
{
modelBuilder.Entity(entityType.ClrType)
.ToTable(tablePrefix + table.Name);
}

最后,还没有完!!

还记得在一开始,我就说了ABP Module Zero内置表有默认的前缀Abp,也就是说在上述反射获得的内置表table.Name将是Abpxxx的形式,如果你不希望表名中出现Abp,可以在反射之后再使用Abp提供的拓展方法将表名修改一下。

ABP框架入门踩坑-配置数据库表前缀的更多相关文章

  1. ABP框架入门踩坑-配置User Secrets

    配置User Secrets ABP踩坑记录-目录 起因 因为以往习惯在User Secrets中保存连接字符串之类信息,但当我把连接字符串移到secrets.json中后,却发现在迁移过程中会报如下 ...

  2. ABP框架入门踩坑-添加实体

    添加实体 ABP踩坑记录-目录 这里我以问答模块为例,记录一下我在创建实体类过程中碰到的一些坑. 审计属性 具体什么是审计属性我这里就不再介绍了,大家可以参考官方文档. 这里我是通过继承定义好的基类来 ...

  3. ABP框架入门踩坑-使用MySQL

    使用MySQL ABP踩坑记录-目录 起因 因为我自用的服务器只是腾讯云1核1G的学生机,不方便装SQL Server,所以转而MySQL. 这里使用的MySQL版本号为 8.0. 解决方案 删除Qi ...

  4. ABP框架源码学习之修改默认数据库表前缀或表名称

    ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 namespace Abp.Zero.EntityFramework { /// <summary> /// Extension ...

  5. 我的微信小程序入门踩坑之旅

    前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...

  6. 【ABP框架系列学习】启动配置(5)

    ABP提供了在启动时配置模块的基础设施和模型. 1.配置ABP 配置ABP是在模块的PreInitialize方法中完成的,例如: public class SimpleTaskSystemModul ...

  7. 项目那几步走:先配置setting路径文件、创建数据库、执行数据库迁移命令、配置mysql数据库信息、注册app、注释中间件、pymysql替换mysqldb-配置urls路由-继续视图函数-然后HTML页面展示-HTML里面导入css文件、models配置数据库表、

    django使用mysql数据库: 首先cmd创建库 1.settings: """Django settings for day42 project. Generate ...

  8. Go ORM框架 - GORM 踩坑指南

    今天聊聊目前业界使用比较多的 ORM 框架:GORM.GORM 相关的文档原作者已经写得非常的详细,具体可以看这里,这一篇主要做一些 GORM 使用过程中关键功能的介绍,GORM 约定的一些配置信息说 ...

  9. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

随机推荐

  1. WCF路由服务

    代码下载: 链接:https://pan.baidu.com/s/1i76Ht0lMWmosaCrDjaA2cA 密码:muj11.新建类库 Service.Interface using Syste ...

  2. JS在页面根据数量改变总价及按钮进行格式验证

    分两部分,第一部分是在页面上,根据数量的input标签内容,动态更新总价标签的内容,代码如下: <script type="text/javascript"> $(do ...

  3. Blob CLOB区别

    区别: CLOB :使用char来保存数据.例如xml文件.文章或者较长的文字. BLOB:就是使用二进制保存数据.例如保存位图.图片音乐. 联系:两者可以互相转换.或者直接用lob字段代替两者. 读 ...

  4. System.load()与System.loadLibrary()

    Java load 和 loadlibrary方法的区别 1.  相同点: 两个方法都是用来装载dll文件,不论是JNI库文件还是非JNI库文件.本地方法在被调用时都需要通过这两发方法之一将其加载至内 ...

  5. kbmmw 中的进程管理小工具

    kbmmw 5.6.20 发布了,本版本带来一个小功能,就是可以在kbmmw 应用里面建立和管理进程, 虽然你可以直接调用windows api 做类似的事情,但是kbmmw 里面简化了操作,也加强了 ...

  6. kbmmw 5.04 发布

    增加了一大波功能,消灭了一大堆问题,也肯定引进了一大票BUG.We are happy to announce the release of our latest version of kbmMW. ...

  7. 代理设计模式 (静态代理设计模式)+ 动态代理(JDK和Cglib)

    一.代理设计模式 1.设计模式:前人总结一套解决特定问题的代码 2.代理设计模式优点: 2.1 保护真实对象 2.2 让真实对象职责更明确 2.3 扩展 3.代理设计模式 3.1 真实对象(老总) 3 ...

  8. https网站引用http路径的js和css失效解决办法

    Jazzy  html  2015-03-26 在https的网站中引用http路径的js或css会导致不起作用,其形如: Html <script src="http://code. ...

  9. 委托构造函数(c++11)

    1.概念 1)委托构造函数也是构造函数,它也有形参列表,它将实参传递给其他的构造函数来初始化类对象,像是把自己的一些(或者全部)构造职责委托给其他构造函数一样

  10. php 微信登录 公众号 获取用户信息 微信网页授权

    php 微信登录 公众号 获取用户信息 微信网页授权 先自己建立两个文件: index.php  和  getUserInfo.php index.php <?php //scope=snsap ...