Admin.Core 源码项目默认使用 SQLite 数据库。项目启动后,数据库文件会自动生成在以下目录:
如需使用其他数据库,可修改配置文件:
1 ConfigCenter/DbConfig.json
下面以 MySQL 创建 bizdb 业务库 为例说明配置方式。其他数据库的操作方式类似。以下配置均位于:
1 DbConfig.json -> DbConfig
安装数据库管理工具 推荐使用 Beekeeper Studio 作为数据库管理工具。
访问 Beekeeper Studio 官网。
点击 Download for Windows 。
在下载页面点击 Skip to the download 。
选择适合当前系统的版本,下载并安装。
创建数据库 以 MySQL 创建 bizdb 数据库为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "syncStructureSql" : false , "createDb" : true , "createDbConnectionString" : "Server=localhost; Port=3306; Database=mysql; Uid=root; Pwd=pwd; Charset=utf8mb4;" , "createDbSql" : "CREATE DATABASE `bizdb` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci'" }
提示 FreeSql 数据库连接字符串示例:
https://freesql.net/guide/#connectionstrings
第三方数据库连接字符串示例:
https://www.connectionstrings.com
SQLite 数据库配置 SQLite 数据库不需要配置建库,只需配置连接字符串,项目启动时会自动创建数据库文件。
1 2 3 4 { "type" : "Sqlite" , "connectionString" : "Data Source=|DataDirectory|\\bizdb.db; Pooling=true;Min Pool Size=1" }
SQLite 数据库文件会创建在以下目录:
1 bin\Debug\net10.0\bizdb.db
连接数据库 以 MySQL 为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "type" : "MySql" , "connectionString" : "Server=localhost; Port=3306; Database=bizdb; Uid=root; Pwd=pwd; Charset=utf8mb4;Min pool size=1;Allow User Variables=True" , "providerType" : "" }
注意 MySQL 8.0 及以上版本,default_authentication_plugin 默认为 caching_sha2_password,推荐使用以下连接字符串:
1 Server=localhost; Port=3306; Database=bizdb; Uid=root; Pwd=pwd; Charset=utf8mb4;Min pool size=1;Allow User Variables=True
同步结构和初始化数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 { "assemblyNames" : [ "MyCompanyName.MySys.Api" ] , "includeEntityDbs" : [ ] , "excludeEntityDbs" : [ ] , "syncStructure" : true , "syncStructureEntityBatchSize" : 1 , "syncDataBatchSize" : 500 , "syncData" : true , "syncUpdateData" : true , "syncDataIncludeTables" : [ ] , "syncDataExcludeTables" : [ ] , "syncDataUser" : { "id" : 161223411986501 , "userName" : "admin" , "name" : "管理员" , "tenantId" : 161223412138053 } }
多数据库配置 配置示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 { "dbs" : [ { "key" : "moduledb" , "assemblyNames" : [ "MyCompanyName.MyModuleName.Api.Contracts" ] , "includeEntityDbs" : [ ] , "excludeEntityDbs" : [ ] , "monitorCommand" : false , "curd" : true , "syncStructureSql" : false , "syncDataCurd" : false , "createDb" : true , "createDbConnectionString" : "" , "createDbSql" : "" , "syncStructure" : true , "syncStructureEntityBatchSize" : 1 , "syncDataBatchSize" : 500 , "syncData" : true , "syncUpdateData" : false , "SyncDataPath" : "InitData/App" , "syncDataIncludeTables" : [ ] , "syncDataExcludeTables" : [ ] , "syncDataUser" : { "id" : 161223411986501 , "userName" : "admin" , "name" : "管理员" , "tenantId" : 161223412138053 } , "generateData" : false , "type" : "Sqlite" , "connectionString" : "Data Source=|DataDirectory|\\moduledb.db; Pooling=true;Min Pool Size=1" , "providerType" : "" , "slaveList" : [ ] } ] }
定义数据库键名 在以下目录中新建 DbKeys.cs 类:
1 MyCompanyName.MyProjectName.Api.Core/Consts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System.ComponentModel;namespace MyCompanyName.MyProjectName.Api.Core.Consts ;public class DbKeys { [Description("模块库注册键" ) ] public static string ModuleDb { get ; set ; } = "moduledb" ; }
其中,ModuleDb 为模块库注册键,可根据需要自定义命名。
新建模块基础仓储类 在以下目录中新建 ModuleRepositoryBase.cs 类:
1 MyCompanyName.MyProjectName.Api/Core/Repositories
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using MyCompanyName.MySys.Api.Core.Consts;using ZhonTai.Admin.Core.Db.Transaction;using ZhonTai.Admin.Core.Repositories;namespace MyCompanyName.MySys.Api.Core.Repositories ;public class ModuleRepositoryBase <TEntity > : RepositoryBase <TEntity > where TEntity : class { public ModuleRepositoryBase (UnitOfWorkManagerCloud uowm ) : base (DbKeys.ModuleDb, uowm ) { } }
配置宿主应用 在 Program.cs 中配置宿主应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 new HostApp(new HostAppOptions{ ConfigurePreServices = context => { DbKeys.ModuleDb = "moduledb" ; }, ConfigureAutofacContainer = (builder, context) => { builder.RegisterGeneric(typeof (ModuleRepositoryBase<>)) .InstancePerLifetimeScope() .PropertiesAutowired(); } });
使用多数据库 方式一:使用 ModuleRepositoryBase 泛型模块基础仓储类 1 2 3 4 5 6 7 8 9 10 11 [Order(1010) ] [DynamicApi(Area = ApiConsts.AreaName) ] public class ModuleService : BaseService , IDynamicApi { private readonly ModuleRepositoryBase<Entity> _moduleRepo; public ModuleService (ModuleRepositoryBase<Entity> moduleRepo ) { _moduleRepo = moduleRepo; } }
方式二:使用 FreeSqlCloud 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ModuleService : BaseService , IDynamicApi { private readonly FreeSqlCloud _freeSqlCloud; public ModuleService (FreeSqlCloud freeSqlCloud ) { _freeSqlCloud = freeSqlCloud; } public void GetData () { var fsql = _freeSqlCloud.Use(DbKeys.ModuleDb); } }
方式三:使用模块仓储接口 定义 IModuleRepository 模块仓储接口 1 2 3 4 5 6 7 8 9 10 11 using MyCompanyName.MySys.Api.Contracts.Domain.Module;using ZhonTai.Admin.Core.Repositories;namespace MyCompanyName.MySys.Api.Contracts ;public interface IModuleRepository : IRepositoryBase <ModuleEntity >{ }
定义 ModuleRepository 模块仓储 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using MyCompanyName.MySys.Api.Contracts;using MyCompanyName.MySys.Api.Contracts.Domain.Module;using MyCompanyName.MySys.Api.Core.Repositories;using ZhonTai.Admin.Core.Db.Transaction;namespace MyCompanyName.MySys.Api.Repositories.Module ;public class ModuleRepository : ModuleRepositoryBase <ModuleEntity >, IModuleRepository { public ModuleRepository (UnitOfWorkManagerCloud uowm ) : base (uowm ) { } }
使用 IModuleRepository 模块仓储接口 1 2 3 4 5 6 7 8 9 10 11 [Order(1010) ] [DynamicApi(Area = ApiConsts.AreaName) ] public class ModuleService : BaseService , IDynamicApi { private readonly IModuleRepository _moduleRepo; public ModuleService (IModuleRepository moduleRepo ) { _moduleRepo = moduleRepo; } }
生成数据 将 *.json 数据文件生成到以下目录:
配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "createDb" : false , "syncStructure" : false , "syncData" : false , "syncUpdateData" : false , "generateData" : true }
提示
项目开发启动时,不建议开启生成数据。
发布生产环境前,如果开发环境存在配置数据需要更新数据包,可以开启生成数据包。
项目发布后,如需更新数据包,也可以开启生成数据包。
使用完成后,请及时关闭 generateData。
自定义生成数据 在以下目录中新建 Data 文件夹,并新增 CustomGenerateData.cs 类:
1 MyCompanyName.MyProjectName.Api/Core/Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System.Threading.Tasks;using ZhonTai.Admin.Core.Configs;using ZhonTai.Admin.Core.Db.Data;using MyCompanyName.MySys.Api.Contracts.Domain.Module;namespace MyCompanyName.MySys.Api.Core.Data ;public class CustomGenerateData : GenerateData , IGenerateData { public virtual async Task GenerateDataAsync (IFreeSql db, AppConfig appConfig ) { var isTenant = appConfig.Tenant; var modules = await db.Queryable<ModuleEntity>().ToListAsync(); SaveDataToJsonFile<ModuleEntity>(modules, isTenant, path: "InitData/App" ); } }
同步数据 将以下目录中的 JSON 数据同步到数据库:
配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 { "syncStructure" : true , "syncData" : true , "syncUpdateData" : true , "generateData" : false }
自定义同步数据 在以下目录中新建 Data 文件夹,并新增 CustomSyncData.cs 类:
1 MyCompanyName.MyProjectName.Api/Core/Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 using System;using System.Threading.Tasks;using ZhonTai.Admin.Core.Configs;using ZhonTai.Admin.Core.Db.Data;using MyCompanyName.MySys.Api.Contracts.Domain.Module;using System.Linq;namespace MyCompanyName.MySys.Api.Core.Data ;public class CustomSyncData : SyncData , ISyncData { public virtual async Task SyncDataAsync (IFreeSql db, DbConfig dbConfig = null , AppConfig appConfig = null ) { using var unitOfWork = db.CreateUnitOfWork(); try { var isTenant = appConfig.Tenant; await SyncEntityAsync<ModuleEntity>( db, unitOfWork, dbConfig, appConfig, whereFunc: (select , batchDataList) => { if (appConfig.Tenant) { return select .Where(a => batchDataList.Any(b => a.Id == b.Id || ( a.TenantId == b.TenantId && !string .IsNullOrWhiteSpace(a.Name) && a.Name == b.Name ) ) ); } return select .Where(a => batchDataList.Any(b => a.Id == b.Id || ( !string .IsNullOrWhiteSpace(a.Name) && a.Name == b.Name ) ) ); }, insertDataFunc: (batchDataList, dbDataList) => { return batchDataList.Where(a => !dbDataList.Any(b => a.Id == b.Id)); } ); unitOfWork.Commit(); } catch (Exception) { unitOfWork.Rollback(); throw ; } } }
数据库事务 使用事务 在服务方法上添加 [AppTransaction] 特性,即可使用当前项目主库事务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 [AppTransaction ] public virtual async Task UpdateAsync (UserUpdateInput input ){ if (!(input?.Id > 0 )) { throw ResultOutput.Exception("请选择用户" ); } var user = await _userRepository.GetAsync(input.Id); if (!(user?.Id > 0 )) { throw ResultOutput.Exception("用户不存在" ); } _mapper.Map(input, user); await _userRepository.UpdateAsync(user); await _userRoleRepository.DeleteAsync(a => a.UserId == user.Id); if (input.RoleIds != null && input.RoleIds.Any()) { var roles = input.RoleIds.Select(a => new UserRoleEntity { UserId = user.Id, RoleId = a }); await _userRoleRepository.InsertAsync(roles); } }
提示
事务可跨方法使用。
支持同步方法和异步方法。
如果服务是动态 API,开启事务的方法需要定义为 virtual 虚方法,事务才能正常生效。
存在多个 CUD 操作时,事务会确保操作要么全部成功,要么全部失败。
事务回滚 推荐抛出友好异常触发事务回滚:
1 throw ResultOutput.Exception(msg);
也可以使用:
1 throw new AppException(msg);
提交事务 如果方法执行过程中没有异常抛出,事务将自动提交。
事务属性
参数
说明
类型
默认值
Propagation
事务传播方式
enum
Required
IsolationLevel
事务隔离级别
enum
-
Propagation 事务传播方式
值
说明
Required
如果当前没有事务,则新建事务;如果已存在事务,则加入当前事务。默认选择。
Supports
支持当前事务;如果没有当前事务,则以非事务方式执行。
Mandatory
使用当前事务;如果没有当前事务,则抛出异常。
NotSupported
以非事务方式执行;如果当前存在事务,则挂起当前事务。
Never
以非事务方式执行;如果当前存在事务,则抛出异常。
Nested
以嵌套事务方式执行。
IsolationLevel 事务隔离级别
值
说明
Chaos
无法覆盖隔离级别更高的事务中挂起的更改。
ReadCommitted
读取数据时保持共享锁,以避免脏读;但事务结束前数据仍可能被更改,从而导致不可重复读或幻读。
ReadUncommitted
允许脏读,不发布共享锁,也不接受独占锁。
RepeatableRead
对查询中使用的所有数据加锁,防止其他用户更新这些数据。可防止不可重复读,但仍可能出现幻读。
Serializable
在数据集上放置范围锁,防止事务完成前其他用户更新行或插入行。
Snapshot
通过在一个应用程序修改数据时保存另一个应用程序可读取的数据版本来减少阻塞。表示当前事务无法看到其他事务中的更改,即使重新查询也是如此。
Unspecified
正在使用与指定隔离级别不同的隔离级别,但无法确定具体级别。
#中台 #中台/.NET模板 #中台/搭建项目框架 #中台/数据库配置 #中台/多数据库配置