配置数据库表前缀

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. JDK8集合类源码解析 - ArrayList

    ArrayList主要要注意以下几点: 1构造方法 2添加add(E e) 3 获取 get(int index) 4 删除 remove(int index)    ,   remove(Objec ...

  2. oracle使用3DES加密

    CREATE OR REPLACE PACKAGE dbc_cryptor IS SYSKEY VARCHAR2(16) := '0000000012345678'; SYSIV VARCHAR2(1 ...

  3. activiti 清库脚本(转)

    在使用activiti 的时候会经常遇到需要清空数据库中的数据,因此本文重点讲解如何解决该问题. 再删除数据的时候,需要注意有主外键约束的问题?下面罗列的DDL可以结合自身的业务需求进行灵活改造. D ...

  4. SpringBoot获取resource下证书失败

    1.第一种失败的情况:    本来使用Spring的上下文容器获取文件,将证书文件放在resource下,编译后获取文件会出现报错 java.security.spec.InvalidKeySpecE ...

  5. Visual Studio 2015部署OpenCV

    Visual Studio 2015的安装破解及OpenCV的安装和部署 平台:win10 X64+VS2015专业版 X64:vs2015.pro_chs+OpenCV 3.X:opencv-3.4 ...

  6. Java的GUI设计小技巧

    不可关闭窗口 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

  7. ssh定义、操作

    Secure Shell(縮寫为SSH)SSH為一项建立在应用层和传输层基础上的安全协议,为计算机上的Shell(壳层)提供安全的传输和使用环境. 传统的网络服务程序,如rsh.FTP.POP和Tel ...

  8. 812. Largest Triangle Area

    static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...

  9. C++航空系统

    /* * SHA-256 implementation, Mark 2 * * Copyright (c) 2010,2014 Ilya O. Levin, http://www.literateco ...

  10. Booksim的运行

    1.下载flex和bison解压到/home/cp/booksim2-master/src; 2.进入flex.bison的目录下分别执行: ./configure make make install ...