diff --git a/aspnet-core/LINGYUN.MicroService.SingleProject.sln b/aspnet-core/LINGYUN.MicroService.SingleProject.sln
index 59f3b420b..919d209bd 100644
--- a/aspnet-core/LINGYUN.MicroService.SingleProject.sln
+++ b/aspnet-core/LINGYUN.MicroService.SingleProject.sln
@@ -666,6 +666,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.Asp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.WeChat.Work", "framework\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj", "{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Saas.DbChecker", "modules\saas\LINGYUN.Abp.Saas.DbChecker\LINGYUN.Abp.Saas.DbChecker.csproj", "{32F0884D-DA64-4659-AEB7-2717B977855F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.MySqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.MySqlInstaller\LINGYUN.Abp.Quartz.MySqlInstaller.csproj", "{B6452D3F-E58C-C433-E52A-F65EE2657E01}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.SqlServerInstaller", "modules\task-management\LINGYUN.Abp.Quartz.SqlServerInstaller\LINGYUN.Abp.Quartz.SqlServerInstaller.csproj", "{D613F393-9CEE-2D3B-33C9-90630F8348E7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.HttpApi.Client", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi.Client\LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj", "{2A8DDC93-94B6-75B4-5B0C-DA72B1AD0E6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Saas.HttpApi.Client", "modules\saas\LINGYUN.Abp.Saas.HttpApi.Client\LINGYUN.Abp.Saas.HttpApi.Client.csproj", "{311C3A82-3B01-79BD-F9C5-FCC2549A9A8D}"
@@ -1780,6 +1785,18 @@ Global
{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {32F0884D-DA64-4659-AEB7-2717B977855F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {32F0884D-DA64-4659-AEB7-2717B977855F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {32F0884D-DA64-4659-AEB7-2717B977855F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {32F0884D-DA64-4659-AEB7-2717B977855F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.Build.0 = Release|Any CPU
{2A8DDC93-94B6-75B4-5B0C-DA72B1AD0E6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A8DDC93-94B6-75B4-5B0C-DA72B1AD0E6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A8DDC93-94B6-75B4-5B0C-DA72B1AD0E6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -2124,6 +2141,9 @@ Global
{C9266D5D-3860-09C3-F566-489BBB57A534} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
+ {32F0884D-DA64-4659-AEB7-2717B977855F} = {0DF5AD76-AEEA-4052-A6CA-A44C24879F11}
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01} = {D9C65C9D-8591-46DA-A3EE-419393E607AB}
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7} = {D9C65C9D-8591-46DA-A3EE-419393E607AB}
{2A8DDC93-94B6-75B4-5B0C-DA72B1AD0E6A} = {D9C65C9D-8591-46DA-A3EE-419393E607AB}
{311C3A82-3B01-79BD-F9C5-FCC2549A9A8D} = {0DF5AD76-AEEA-4052-A6CA-A44C24879F11}
{F2A31684-7A38-B77D-CCAA-C21B9A8B45CF} = {42F31C68-B8B2-4BE0-9AD0-A7DFA6092629}
diff --git a/aspnet-core/LINGYUN.MicroService.TaskManagement.sln b/aspnet-core/LINGYUN.MicroService.TaskManagement.sln
index 57236d16e..84f9888fd 100644
--- a/aspnet-core/LINGYUN.MicroService.TaskManagement.sln
+++ b/aspnet-core/LINGYUN.MicroService.TaskManagement.sln
@@ -170,6 +170,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Sms.Platform",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.SkyWalking", "framework\telemetry\LINGYUN.Abp.Telemetry.SkyWalking\LINGYUN.Abp.Telemetry.SkyWalking.csproj", "{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.MySqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.MySqlInstaller\LINGYUN.Abp.Quartz.MySqlInstaller.csproj", "{B6452D3F-E58C-C433-E52A-F65EE2657E01}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.SqlServerInstaller", "modules\task-management\LINGYUN.Abp.Quartz.SqlServerInstaller\LINGYUN.Abp.Quartz.SqlServerInstaller.csproj", "{D613F393-9CEE-2D3B-33C9-90630F8348E7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -436,6 +440,14 @@ Global
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -506,6 +518,8 @@ Global
{8BAB6A91-865C-A599-BE2A-7C487129D83A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{8298C4A6-5275-D7A2-9A5C-99B5F2D0E7A0} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE} = {5A41C31A-B966-418B-B446-5BA1D7E61A62}
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01} = {385578CC-C0F1-4377-A7A2-682B8F416234}
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7} = {385578CC-C0F1-4377-A7A2-682B8F416234}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E1FD1F4C-D344-408B-97CF-B6F1F6D7D293}
diff --git a/aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln b/aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln
index cc5c8e797..e30af9fe4 100644
--- a/aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln
+++ b/aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln
@@ -167,6 +167,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.SkyWa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "telemetry", "telemetry", "{CE07B9F4-54E8-4E74-BE14-8E5C1FB7AFC8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.MySqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.MySqlInstaller\LINGYUN.Abp.Quartz.MySqlInstaller.csproj", "{B6452D3F-E58C-C433-E52A-F65EE2657E01}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.SqlServerInstaller", "modules\task-management\LINGYUN.Abp.Quartz.SqlServerInstaller\LINGYUN.Abp.Quartz.SqlServerInstaller.csproj", "{D613F393-9CEE-2D3B-33C9-90630F8348E7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -429,6 +433,14 @@ Global
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -512,6 +524,8 @@ Global
{8BAB6A91-865C-A599-BE2A-7C487129D83A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE} = {CE07B9F4-54E8-4E74-BE14-8E5C1FB7AFC8}
{CE07B9F4-54E8-4E74-BE14-8E5C1FB7AFC8} = {03B4B0AA-83CE-4E4B-9CE2-47369BF88B97}
+ {B6452D3F-E58C-C433-E52A-F65EE2657E01} = {8C3DF571-BAC3-48C4-B46A-AC0E0EAA9871}
+ {D613F393-9CEE-2D3B-33C9-90630F8348E7} = {8C3DF571-BAC3-48C4-B46A-AC0E0EAA9871}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {80ED12A5-C899-459F-A181-ADCC9D680DE5}
diff --git a/aspnet-core/LINGYUN.MicroService.Workflow.sln b/aspnet-core/LINGYUN.MicroService.Workflow.sln
index e26f6f05c..aced25869 100644
--- a/aspnet-core/LINGYUN.MicroService.Workflow.sln
+++ b/aspnet-core/LINGYUN.MicroService.Workflow.sln
@@ -189,6 +189,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.WorkflowMan
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.SkyWalking", "framework\telemetry\LINGYUN.Abp.Telemetry.SkyWalking\LINGYUN.Abp.Telemetry.SkyWalking.csproj", "{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.MySqlInstaller", "modules\task-management\LINGYUN.Abp.Quartz.MySqlInstaller\LINGYUN.Abp.Quartz.MySqlInstaller.csproj", "{B5C96536-6387-44F4-A2E2-D4D683588AF5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Quartz.SqlServerInstaller", "modules\task-management\LINGYUN.Abp.Quartz.SqlServerInstaller\LINGYUN.Abp.Quartz.SqlServerInstaller.csproj", "{52F5A9DE-50B8-42C6-9980-E908DC6A4B52}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -495,6 +499,14 @@ Global
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B5C96536-6387-44F4-A2E2-D4D683588AF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B5C96536-6387-44F4-A2E2-D4D683588AF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B5C96536-6387-44F4-A2E2-D4D683588AF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B5C96536-6387-44F4-A2E2-D4D683588AF5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {52F5A9DE-50B8-42C6-9980-E908DC6A4B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {52F5A9DE-50B8-42C6-9980-E908DC6A4B52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {52F5A9DE-50B8-42C6-9980-E908DC6A4B52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {52F5A9DE-50B8-42C6-9980-E908DC6A4B52}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -581,6 +593,8 @@ Global
{9CD04B74-AA10-4253-BEEC-4837D48AD3EB} = {6CB521FC-AC40-49A6-B9A5-91399CAA59AB}
{09CDA563-DE16-41F6-B61C-56102E7D9B2E} = {9CD04B74-AA10-4253-BEEC-4837D48AD3EB}
{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
+ {B5C96536-6387-44F4-A2E2-D4D683588AF5} = {7844FF58-7DBF-46E1-88B7-9764382A4EE9}
+ {52F5A9DE-50B8-42C6-9980-E908DC6A4B52} = {7844FF58-7DBF-46E1-88B7-9764382A4EE9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj
index ab9fcb726..e77867d78 100644
--- a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.csproj
@@ -13,6 +13,14 @@
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/AbpElsaEntityFrameworkCoreMySqlModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/AbpElsaEntityFrameworkCoreMySqlModule.cs
index 45069e0a8..5b8ce2f5a 100644
--- a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/AbpElsaEntityFrameworkCoreMySqlModule.cs
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/AbpElsaEntityFrameworkCoreMySqlModule.cs
@@ -3,6 +3,7 @@ using Elsa.Options;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql;
@@ -26,4 +27,12 @@ public class AbpElsaEntityFrameworkCoreMySqlModule : AbpModule
elsa.AddFeatures(startups, configuration);
});
}
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+ }
}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/Initial.sql b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/Initial.sql
new file mode 100644
index 000000000..0ca9b20ae
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/Initial.sql
@@ -0,0 +1,315 @@
+-- basic script
+
+USE `${DataBase}`;
+
+CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
+ `MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
+ `ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
+ CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
+) CHARACTER SET utf8mb4;
+
+START TRANSACTION;
+
+ALTER DATABASE CHARACTER SET utf8mb4;
+
+CREATE TABLE `Bookmarks` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Hash` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `Model` longtext CHARACTER SET utf8mb4 NOT NULL,
+ `ModelType` longtext CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `WorkflowInstanceId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ CONSTRAINT `PK_Bookmarks` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `WorkflowDefinitions` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `DefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Name` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `DisplayName` longtext CHARACTER SET utf8mb4 NULL,
+ `Description` longtext CHARACTER SET utf8mb4 NULL,
+ `Version` int NOT NULL,
+ `IsSingleton` tinyint(1) NOT NULL,
+ `PersistenceBehavior` int NOT NULL,
+ `DeleteCompletedInstances` tinyint(1) NOT NULL,
+ `IsPublished` tinyint(1) NOT NULL,
+ `IsLatest` tinyint(1) NOT NULL,
+ `Tag` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Data` longtext CHARACTER SET utf8mb4 NULL,
+ CONSTRAINT `PK_WorkflowDefinitions` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `WorkflowExecutionLogRecords` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `WorkflowInstanceId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `Timestamp` datetime(6) NOT NULL,
+ `EventName` longtext CHARACTER SET utf8mb4 NULL,
+ `Message` longtext CHARACTER SET utf8mb4 NULL,
+ `Source` longtext CHARACTER SET utf8mb4 NULL,
+ `Data` longtext CHARACTER SET utf8mb4 NULL,
+ CONSTRAINT `PK_WorkflowExecutionLogRecords` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `WorkflowInstances` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `DefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Version` int NOT NULL,
+ `WorkflowStatus` int NOT NULL,
+ `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `ContextType` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `ContextId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Name` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `CreatedAt` datetime(6) NOT NULL,
+ `LastExecutedAt` datetime(6) NULL,
+ `FinishedAt` datetime(6) NULL,
+ `CancelledAt` datetime(6) NULL,
+ `FaultedAt` datetime(6) NULL,
+ `Data` longtext CHARACTER SET utf8mb4 NULL,
+ CONSTRAINT `PK_WorkflowInstances` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE INDEX `IX_Bookmark_ActivityId` ON `Bookmarks` (`ActivityId`);
+
+CREATE INDEX `IX_Bookmark_ActivityType` ON `Bookmarks` (`ActivityType`);
+
+CREATE INDEX `IX_Bookmark_ActivityType_TenantId_Hash` ON `Bookmarks` (`ActivityType`, `TenantId`, `Hash`);
+
+CREATE INDEX `IX_Bookmark_CorrelationId` ON `Bookmarks` (`CorrelationId`);
+
+CREATE INDEX `IX_Bookmark_Hash` ON `Bookmarks` (`Hash`);
+
+CREATE INDEX `IX_Bookmark_Hash_CorrelationId_TenantId` ON `Bookmarks` (`Hash`, `CorrelationId`, `TenantId`);
+
+CREATE INDEX `IX_Bookmark_TenantId` ON `Bookmarks` (`TenantId`);
+
+CREATE INDEX `IX_Bookmark_WorkflowInstanceId` ON `Bookmarks` (`WorkflowInstanceId`);
+
+CREATE UNIQUE INDEX `IX_WorkflowDefinition_DefinitionId_VersionId` ON `WorkflowDefinitions` (`DefinitionId`, `Version`);
+
+CREATE INDEX `IX_WorkflowDefinition_IsLatest` ON `WorkflowDefinitions` (`IsLatest`);
+
+CREATE INDEX `IX_WorkflowDefinition_IsPublished` ON `WorkflowDefinitions` (`IsPublished`);
+
+CREATE INDEX `IX_WorkflowDefinition_Name` ON `WorkflowDefinitions` (`Name`);
+
+CREATE INDEX `IX_WorkflowDefinition_Tag` ON `WorkflowDefinitions` (`Tag`);
+
+CREATE INDEX `IX_WorkflowDefinition_TenantId` ON `WorkflowDefinitions` (`TenantId`);
+
+CREATE INDEX `IX_WorkflowDefinition_Version` ON `WorkflowDefinitions` (`Version`);
+
+CREATE INDEX `IX_WorkflowExecutionLogRecord_ActivityId` ON `WorkflowExecutionLogRecords` (`ActivityId`);
+
+CREATE INDEX `IX_WorkflowExecutionLogRecord_ActivityType` ON `WorkflowExecutionLogRecords` (`ActivityType`);
+
+CREATE INDEX `IX_WorkflowExecutionLogRecord_TenantId` ON `WorkflowExecutionLogRecords` (`TenantId`);
+
+CREATE INDEX `IX_WorkflowExecutionLogRecord_Timestamp` ON `WorkflowExecutionLogRecords` (`Timestamp`);
+
+CREATE INDEX `IX_WorkflowExecutionLogRecord_WorkflowInstanceId` ON `WorkflowExecutionLogRecords` (`WorkflowInstanceId`);
+
+CREATE INDEX `IX_WorkflowInstance_ContextId` ON `WorkflowInstances` (`ContextId`);
+
+CREATE INDEX `IX_WorkflowInstance_ContextType` ON `WorkflowInstances` (`ContextType`);
+
+CREATE INDEX `IX_WorkflowInstance_CorrelationId` ON `WorkflowInstances` (`CorrelationId`);
+
+CREATE INDEX `IX_WorkflowInstance_CreatedAt` ON `WorkflowInstances` (`CreatedAt`);
+
+CREATE INDEX `IX_WorkflowInstance_DefinitionId` ON `WorkflowInstances` (`DefinitionId`);
+
+CREATE INDEX `IX_WorkflowInstance_FaultedAt` ON `WorkflowInstances` (`FaultedAt`);
+
+CREATE INDEX `IX_WorkflowInstance_FinishedAt` ON `WorkflowInstances` (`FinishedAt`);
+
+CREATE INDEX `IX_WorkflowInstance_LastExecutedAt` ON `WorkflowInstances` (`LastExecutedAt`);
+
+CREATE INDEX `IX_WorkflowInstance_Name` ON `WorkflowInstances` (`Name`);
+
+CREATE INDEX `IX_WorkflowInstance_TenantId` ON `WorkflowInstances` (`TenantId`);
+
+CREATE INDEX `IX_WorkflowInstance_WorkflowStatus` ON `WorkflowInstances` (`WorkflowStatus`);
+
+CREATE INDEX `IX_WorkflowInstance_WorkflowStatus_DefinitionId` ON `WorkflowInstances` (`WorkflowStatus`, `DefinitionId`);
+
+CREATE INDEX `IX_WorkflowInstance_WorkflowStatus_DefinitionId_Version` ON `WorkflowInstances` (`WorkflowStatus`, `DefinitionId`, `Version`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210523093427_Initial', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `WorkflowInstances` MODIFY COLUMN `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '';
+
+ALTER TABLE `WorkflowInstances` ADD `LastExecutedActivityId` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `WorkflowDefinitions` ADD `OutputStorageProviderName` longtext CHARACTER SET utf8mb4 NULL;
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210611200027_Update21', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `WorkflowDefinitions` DROP COLUMN `OutputStorageProviderName`;
+
+ALTER TABLE `WorkflowInstances` RENAME `WorkflowInstances`;
+
+ALTER TABLE `WorkflowExecutionLogRecords` RENAME `WorkflowExecutionLogRecords`;
+
+ALTER TABLE `WorkflowDefinitions` RENAME `WorkflowDefinitions`;
+
+ALTER TABLE `Bookmarks` RENAME `Bookmarks`;
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210923112211_Update23', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `WorkflowInstances` ADD `DefinitionVersionId` longtext CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `Bookmarks` MODIFY COLUMN `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '';
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20211215100204_Update24', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `WorkflowInstances` MODIFY COLUMN `DefinitionVersionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL;
+
+CREATE INDEX `IX_WorkflowInstance_DefinitionVersionId` ON `WorkflowInstances` (`DefinitionVersionId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20220120170050_Update241', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+CREATE TABLE `Triggers` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Hash` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `Model` longtext CHARACTER SET utf8mb4 NOT NULL,
+ `ModelType` longtext CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `WorkflowDefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ CONSTRAINT `PK_Triggers` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE INDEX `IX_Trigger_ActivityId` ON `Triggers` (`ActivityId`);
+
+CREATE INDEX `IX_Trigger_ActivityType` ON `Triggers` (`ActivityType`);
+
+CREATE INDEX `IX_Trigger_ActivityType_TenantId_Hash` ON `Triggers` (`ActivityType`, `TenantId`, `Hash`);
+
+CREATE INDEX `IX_Trigger_Hash` ON `Triggers` (`Hash`);
+
+CREATE INDEX `IX_Trigger_Hash_TenantId` ON `Triggers` (`Hash`, `TenantId`);
+
+CREATE INDEX `IX_Trigger_TenantId` ON `Triggers` (`TenantId`);
+
+CREATE INDEX `IX_Trigger_WorkflowDefinitionId` ON `Triggers` (`WorkflowDefinitionId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20220120204150_Update25', '5.0.10');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `WorkflowDefinitions` ADD `CreatedAt` datetime(6) NOT NULL DEFAULT '0001-01-01 00:00:00';
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20220512203646_Update28', '5.0.10');
+
+COMMIT;
+
+
+-- webhooks
+
+CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
+ `MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
+ `ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
+ CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
+) CHARACTER SET utf8mb4;
+
+START TRANSACTION;
+
+ALTER DATABASE CHARACTER SET utf8mb4;
+
+CREATE TABLE `WebhookDefinitions` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `TenantId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `Path` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `Description` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `PayloadTypeName` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `IsEnabled` tinyint(1) NOT NULL,
+ CONSTRAINT `PK_WebhookDefinitions` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE INDEX `IX_WebhookDefinition_Description` ON `WebhookDefinitions` (`Description`);
+
+CREATE INDEX `IX_WebhookDefinition_IsEnabled` ON `WebhookDefinitions` (`IsEnabled`);
+
+CREATE INDEX `IX_WebhookDefinition_Name` ON `WebhookDefinitions` (`Name`);
+
+CREATE INDEX `IX_WebhookDefinition_Path` ON `WebhookDefinitions` (`Path`);
+
+CREATE INDEX `IX_WebhookDefinition_PayloadTypeName` ON `WebhookDefinitions` (`PayloadTypeName`);
+
+CREATE INDEX `IX_WebhookDefinition_TenantId` ON `WebhookDefinitions` (`TenantId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210604065041_Initial', '5.0.10');
+
+COMMIT;
+
+
+-- workflow-settings
+
+CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
+ `MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
+ `ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
+ CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
+) CHARACTER SET utf8mb4;
+
+START TRANSACTION;
+
+ALTER DATABASE CHARACTER SET utf8mb4;
+
+CREATE TABLE `WorkflowSettings` (
+ `Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
+ `WorkflowBlueprintId` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Key` varchar(255) CHARACTER SET utf8mb4 NULL,
+ `Value` varchar(255) CHARACTER SET utf8mb4 NULL,
+ CONSTRAINT `PK_WorkflowSettings` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE INDEX `IX_WorkflowSetting_Key` ON `WorkflowSettings` (`Key`);
+
+CREATE INDEX `IX_WorkflowSetting_Value` ON `WorkflowSettings` (`Value`);
+
+CREATE INDEX `IX_WorkflowSetting_WorkflowBlueprintId` ON `WorkflowSettings` (`WorkflowBlueprintId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210730112043_Initial', '5.0.10');
+
+COMMIT;
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/MySqlElsaDataBaseInstaller.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/MySqlElsaDataBaseInstaller.cs
new file mode 100644
index 000000000..2c3fbdddb
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/MySqlElsaDataBaseInstaller.cs
@@ -0,0 +1,130 @@
+using LINGYUN.Abp.Elsa.EntityFrameworkCore.Migrations;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using MySqlConnector;
+using System;
+using System.Data;
+using System.Threading.Tasks;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.VirtualFileSystem;
+
+namespace LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.Migrations;
+
+[Dependency(ReplaceServices = true)]
+public class MySqlElsaDataBaseInstaller : IElsaDataBaseInstaller, ITransientDependency
+{
+ public ILogger Logger { protected get; set; }
+
+ private readonly IVirtualFileProvider _virtualFileProvider;
+ private readonly IConnectionStringResolver _connectionStringResolver;
+
+ public MySqlElsaDataBaseInstaller(
+ IVirtualFileProvider virtualFileProvider,
+ IConnectionStringResolver connectionStringResolver)
+ {
+ _virtualFileProvider = virtualFileProvider;
+ _connectionStringResolver = connectionStringResolver;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async virtual Task InstallAsync()
+ {
+ var connectionString = await _connectionStringResolver.ResolveAsync("Workflow");
+ if (connectionString.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning("Please configure the `Workflow` database connection string Workflow!");
+ throw new ArgumentNullException(nameof(connectionString));
+ }
+
+ var builder = new MySqlConnectionStringBuilder(connectionString);
+
+ var dataBaseName = await CreateDataBaseIfNotExists(builder.Database, builder);
+
+ builder.Database = dataBaseName;
+
+ using var mySqlConnection = new MySqlConnection(builder.ConnectionString);
+
+ if (mySqlConnection.State == ConnectionState.Closed)
+ {
+ await mySqlConnection.OpenAsync();
+ }
+
+ using (var mySqlCommand = new MySqlCommand("SELECT COUNT(1) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = @DataBaseName;", mySqlConnection))
+ {
+ mySqlCommand.Parameters.Add("@DataBaseName", MySqlDbType.String).Value = dataBaseName;
+
+ var rowsAffects = await mySqlCommand.ExecuteScalarAsync() as long?;
+ if (rowsAffects > 0)
+ {
+ Logger.LogInformation($"The `{dataBaseName}` database has already exists.");
+ return;
+ }
+ }
+
+ var sqlScript = await GetInitSqlScript();
+
+ // USE `${DataBase}` -> USE `Workflow`;;
+ sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName);
+
+ using (var mySqlCommand = new MySqlCommand(sqlScript, mySqlConnection))
+ {
+ Logger.LogInformation("The database initialization script `Initial.sql` starts...");
+
+ await mySqlCommand.ExecuteNonQueryAsync();
+ }
+
+ Logger.LogInformation("Database initialization script `Initial.sql` complete!");
+ }
+
+ public async virtual Task CreateDataBaseIfNotExists(string dataBase, MySqlConnectionStringBuilder connectionStringBuilder)
+ {
+ // 切换主数据库查询数据库是否存在
+ connectionStringBuilder.Database = "mysql";
+ using var mySqlConnection = new MySqlConnection(connectionStringBuilder.ConnectionString);
+ if (mySqlConnection.State == ConnectionState.Closed)
+ {
+ await mySqlConnection.OpenAsync();
+ }
+
+ var checkDataBaseName = "";
+ using (var mySqlCommand = new MySqlCommand("SELECT `SCHEMA_NAME` FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME` = @DataBaseName;", mySqlConnection))
+ {
+ var dataBaseParamter = mySqlCommand.Parameters.Add("DataBaseName", DbType.String);
+ dataBaseParamter.Value = dataBase;
+
+ checkDataBaseName = await mySqlCommand.ExecuteScalarAsync() as string;
+ }
+
+ if (checkDataBaseName.IsNullOrWhiteSpace())
+ {
+ using (var mySqlCommand = new MySqlCommand($"CREATE DATABASE `{dataBase}` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';", mySqlConnection))
+ {
+ await mySqlCommand.ExecuteNonQueryAsync();
+ }
+ }
+
+ return dataBase;
+ }
+
+ public async virtual Task GetInitSqlScript()
+ {
+ var sqlScriptFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Elsa/EntityFrameworkCore/MySql/Migrations/Initial.sql");
+ if (!sqlScriptFileInfo.Exists || sqlScriptFileInfo.IsDirectory)
+ {
+ Logger.LogWarning("Please Check that the `Initial.sql` file exists!");
+ throw new InvalidOperationException("The `Initial.sql` database initialization script file does not exist or is not valid!");
+ }
+
+ var sqlScript = await sqlScriptFileInfo.ReadAsStringAsync();
+ if (sqlScript.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning("The contents of the `Initial.sql` file are empty or invalid!");
+ throw new InvalidOperationException("The contents of the `Initial.sql` file are empty or invalid!");
+ }
+
+ return sqlScript;
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/AbpElsaEntityFrameworkCoreModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/AbpElsaEntityFrameworkCoreModule.cs
index 8d5ba8a20..025f6fb61 100644
--- a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/AbpElsaEntityFrameworkCoreModule.cs
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/AbpElsaEntityFrameworkCoreModule.cs
@@ -1,4 +1,8 @@
-using Volo.Abp.EntityFrameworkCore;
+using LINGYUN.Abp.Elsa.EntityFrameworkCore.Migrations;
+using Microsoft.Extensions.DependencyInjection;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Elsa.EntityFrameworkCore;
@@ -8,4 +12,11 @@ namespace LINGYUN.Abp.Elsa.EntityFrameworkCore;
typeof(AbpEntityFrameworkCoreModule))]
public class AbpElsaEntityFrameworkCoreModule : AbpModule
{
+ public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
+ {
+ // 实现 IElsaStoreMigrator 接口自动初始化数据库
+ await context.ServiceProvider
+ .GetService()
+ ?.InstallAsync();
+ }
}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/Migrations/IElsaDataBaseInstaller.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/Migrations/IElsaDataBaseInstaller.cs
new file mode 100644
index 000000000..14a98839a
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa.EntityFrameworkCore/LINGYUN/Abp/Elsa/EntityFrameworkCore/Migrations/IElsaDataBaseInstaller.cs
@@ -0,0 +1,8 @@
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Elsa.EntityFrameworkCore.Migrations;
+
+public interface IElsaDataBaseInstaller
+{
+ Task InstallAsync();
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckInput.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckInput.cs
new file mode 100644
index 000000000..0adf83f11
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckInput.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+using Volo.Abp.Auditing;
+using Volo.Abp.Validation;
+
+namespace LINGYUN.Abp.Saas.Tenants;
+
+public class TenantConnectionStringCheckInput
+{
+ [Required]
+ public string Provider { get; set; }
+
+ public string Name { get; set; }
+
+ [Required]
+ [DisableAuditing]
+ [DynamicStringLength(typeof(TenantConnectionStringConsts), nameof(TenantConnectionStringConsts.MaxValueLength))]
+ public string ConnectionString { get; set; }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckResultDto.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckResultDto.cs
new file mode 100644
index 000000000..ba9766ebe
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/Dto/TenantConnectionStringCheckResultDto.cs
@@ -0,0 +1,15 @@
+namespace LINGYUN.Abp.Saas.Tenants;
+
+public class TenantConnectionStringCheckResultDto
+{
+ public bool Connected { get; set; }
+ public TenantConnectionStringCheckResultDto()
+ {
+
+ }
+
+ public TenantConnectionStringCheckResultDto(bool connected)
+ {
+ Connected = connected;
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/ITenantAppService.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/ITenantAppService.cs
index db5a30ad1..25575cbec 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/ITenantAppService.cs
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application.Contracts/LINGYUN/Abp/Saas/Tenants/ITenantAppService.cs
@@ -31,4 +31,6 @@ public interface ITenantAppService :
Task DeleteConnectionStringAsync(
Guid id,
[Required] string connectionName);
+
+ Task CheckConnectionStringAsync(TenantConnectionStringCheckInput input);
}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs
index 682914293..c3f938279 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs
@@ -1,6 +1,7 @@
using LINGYUN.Abp.Saas.Features;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -20,18 +21,18 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
protected IDistributedEventBus EventBus { get; }
protected ITenantRepository TenantRepository { get; }
protected ITenantManager TenantManager { get; }
- protected IConnectionStringChecker ConnectionStringChecker { get; }
+ protected AbpSaasConnectionStringCheckOptions ConnectionStringCheckOptions { get; }
public TenantAppService(
ITenantRepository tenantRepository,
ITenantManager tenantManager,
IDistributedEventBus eventBus,
- IConnectionStringChecker connectionStringChecker)
+ IOptions connectionStringCheckOptions)
{
EventBus = eventBus;
TenantRepository = tenantRepository;
TenantManager = tenantManager;
- ConnectionStringChecker = connectionStringChecker;
+ ConnectionStringCheckOptions = connectionStringCheckOptions.Value;
}
public async virtual Task GetAsync(Guid id)
@@ -85,14 +86,12 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
if (!input.UseSharedDatabase)
{
- await CheckConnectionString(input.DefaultConnectionString);
tenant.SetDefaultConnectionString(input.DefaultConnectionString);
if (input.ConnectionStrings.Any())
{
foreach (var connectionString in input.ConnectionStrings)
{
- await CheckConnectionString(connectionString.Value, connectionString.Name);
tenant.SetConnectionString(connectionString.Name, connectionString.Value);
}
}
@@ -215,8 +214,6 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
[Authorize(AbpSaasPermissions.Tenants.ManageConnectionStrings)]
public async virtual Task SetConnectionStringAsync(Guid id, TenantConnectionStringSetInput input)
{
- await CheckConnectionString(input.Value, input.Name);
-
var tenant = await TenantRepository.GetAsync(id);
var oldConnectionString = tenant.FindConnectionString(input.Name);
@@ -275,33 +272,34 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
await CurrentUnitOfWork.SaveChangesAsync();
}
- protected async virtual Task CheckConnectionString(string connectionString, string name = null)
+ public async virtual Task CheckConnectionStringAsync(TenantConnectionStringCheckInput input)
{
- try
+ if (!ConnectionStringCheckOptions.ConnectionStringCheckers.TryGetValue(input.Provider, out var connectionStringChecker))
{
- var checkResult = await ConnectionStringChecker.CheckAsync(connectionString);
- // 检查连接是否可用
- if (!checkResult.Connected)
- {
- throw name.IsNullOrWhiteSpace()
- ? new BusinessException(AbpSaasErrorCodes.InvalidDefaultConnectionString)
- : new BusinessException(AbpSaasErrorCodes.InvalidConnectionString)
- .WithData("Name", name);
- }
- // 默认连接字符串改变不能影响到现有数据库
- if (checkResult.DatabaseExists && name.IsNullOrWhiteSpace())
- {
- throw new BusinessException(AbpSaasErrorCodes.DefaultConnectionStringDatabaseExists);
- }
+ throw new BusinessException(AbpSaasErrorCodes.ConnectionStringProviderNotSupport)
+ .WithData("Name", input.Provider);
}
- catch (Exception e)
+
+ var checkResult = await connectionStringChecker.CheckAsync(input.ConnectionString);
+
+ if (checkResult.Error != null)
+ {
+ Logger.LogWarning(checkResult.Error, "An error occurred while checking the database connection.");
+ }
+
+ // 检查连接是否可用
+ if (!checkResult.Connected)
{
- Logger.LogWarning("An error occurred while checking the validity of the connection string");
- Logger.LogWarning(e.Message);
- throw name.IsNullOrWhiteSpace()
+ throw input.Name.IsNullOrWhiteSpace()
? new BusinessException(AbpSaasErrorCodes.InvalidDefaultConnectionString)
: new BusinessException(AbpSaasErrorCodes.InvalidConnectionString)
- .WithData("Name", name);
+ .WithData("Name", input.Name);
}
+ // 默认连接字符串改变不能影响到现有数据库
+ // 移除此检查, 需要配合数据库迁移才有效
+ //if (checkResult.DatabaseExists && (input.Name.IsNullOrWhiteSpace() || "Default".Equals(input.Name, StringComparison.InvariantCultureIgnoreCase)))
+ //{
+ // throw new BusinessException(AbpSaasErrorCodes.DefaultConnectionStringDatabaseExists);
+ //}
}
}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xml b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xsd b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xsd
new file mode 100644
index 000000000..3f3946e28
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN.Abp.Saas.DbChecker.csproj b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN.Abp.Saas.DbChecker.csproj
new file mode 100644
index 000000000..fd82b2d2c
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN.Abp.Saas.DbChecker.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ net9.0
+ LINGYUN.Abp.Saas.DbChecker
+ LINGYUN.Abp.Saas.DbChecker
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/AbpSaasDbCheckerModule.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/AbpSaasDbCheckerModule.cs
new file mode 100644
index 000000000..d080185c3
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/AbpSaasDbCheckerModule.cs
@@ -0,0 +1,24 @@
+using LINGYUN.Abp.Saas.MySql;
+using LINGYUN.Abp.Saas.Oracle;
+using LINGYUN.Abp.Saas.PostgreSql;
+using LINGYUN.Abp.Saas.Sqlite;
+using LINGYUN.Abp.Saas.SqlServer;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Saas;
+
+[DependsOn(typeof(AbpSaasDomainModule))]
+public class AbpSaasDbCheckerModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.ConnectionStringCheckers["mysql"] = new MySqlConnectionStringChecker();
+ options.ConnectionStringCheckers["oracle"] = new OracleConnectionStringChecker();
+ options.ConnectionStringCheckers["postgres"] = new NpgsqlConnectionStringChecker();
+ options.ConnectionStringCheckers["sqlite"] = new SqliteConnectionStringChecker();
+ options.ConnectionStringCheckers["sqlserver"] = new SqlServerConnectionStringChecker();
+ });
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/MySql/MySqlConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/MySql/MySqlConnectionStringChecker.cs
new file mode 100644
index 000000000..1fd6d1887
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/MySql/MySqlConnectionStringChecker.cs
@@ -0,0 +1,39 @@
+using LINGYUN.Abp.Saas.Tenants;
+using MySqlConnector;
+using System;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Saas.MySql;
+
+public class MySqlConnectionStringChecker : IDataBaseConnectionStringChecker
+{
+ public virtual async Task CheckAsync(string connectionString)
+ {
+ var result = new DataBaseConnectionStringCheckResult();
+ var connString = new MySqlConnectionStringBuilder(connectionString)
+ {
+ ConnectionLifeTime = 1
+ };
+
+ var oldDatabaseName = connString.Database;
+ connString.Database = "mysql";
+
+ try
+ {
+ await using var conn = new MySqlConnection(connString.ConnectionString);
+ await conn.OpenAsync();
+ result.Connected = true;
+ await conn.ChangeDatabaseAsync(oldDatabaseName);
+ result.DatabaseExists = true;
+
+ await conn.CloseAsync();
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ result.Error = e;
+ return result;
+ }
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Oracle/OracleConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Oracle/OracleConnectionStringChecker.cs
new file mode 100644
index 000000000..2651598bc
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Oracle/OracleConnectionStringChecker.cs
@@ -0,0 +1,35 @@
+using LINGYUN.Abp.Saas.Tenants;
+using Oracle.ManagedDataAccess.Client;
+using System;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Saas.Oracle;
+
+public class OracleConnectionStringChecker : IDataBaseConnectionStringChecker
+{
+ public virtual async Task CheckAsync(string connectionString)
+ {
+ var result = new DataBaseConnectionStringCheckResult();
+ var connString = new OracleConnectionStringBuilder(connectionString)
+ {
+ ConnectionTimeout = 1
+ };
+
+ try
+ {
+ await using var conn = new OracleConnection(connString.ConnectionString);
+ await conn.OpenAsync();
+ result.Connected = true;
+ result.DatabaseExists = true;
+
+ await conn.CloseAsync();
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ result.Error = e;
+ return result;
+ }
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/PostgreSql/NpgsqlConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/PostgreSql/NpgsqlConnectionStringChecker.cs
new file mode 100644
index 000000000..89c4cf444
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/PostgreSql/NpgsqlConnectionStringChecker.cs
@@ -0,0 +1,40 @@
+using LINGYUN.Abp.Saas.Tenants;
+using Npgsql;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.Saas.PostgreSql;
+
+public class NpgsqlConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency
+{
+ public virtual async Task CheckAsync(string connectionString)
+ {
+ var result = new DataBaseConnectionStringCheckResult();
+ var connString = new NpgsqlConnectionStringBuilder(connectionString)
+ {
+ Timeout = 1
+ };
+
+ var oldDatabaseName = connString.Database;
+ connString.Database = "postgres";
+
+ try
+ {
+ await using var conn = new NpgsqlConnection(connString.ConnectionString);
+ await conn.OpenAsync();
+ result.Connected = true;
+ await conn.ChangeDatabaseAsync(oldDatabaseName!);
+ result.DatabaseExists = true;
+
+ await conn.CloseAsync();
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ result.Error = e;
+ return result;
+ }
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/SqlServer/SqlServerConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/SqlServer/SqlServerConnectionStringChecker.cs
new file mode 100644
index 000000000..52f3d07f7
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/SqlServer/SqlServerConnectionStringChecker.cs
@@ -0,0 +1,40 @@
+using LINGYUN.Abp.Saas.Tenants;
+using Microsoft.Data.SqlClient;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.Saas.SqlServer;
+
+public class SqlServerConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency
+{
+ public virtual async Task CheckAsync(string connectionString)
+ {
+ var result = new DataBaseConnectionStringCheckResult();
+ var connString = new SqlConnectionStringBuilder(connectionString)
+ {
+ ConnectTimeout = 1
+ };
+
+ var oldDatabaseName = connString.InitialCatalog;
+ connString.InitialCatalog = "master";
+
+ try
+ {
+ await using var conn = new SqlConnection(connString.ConnectionString);
+ await conn.OpenAsync();
+ result.Connected = true;
+ await conn.ChangeDatabaseAsync(oldDatabaseName);
+ result.DatabaseExists = true;
+
+ await conn.CloseAsync();
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ result.Error = e;
+ return result;
+ }
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Sqlite/SqliteConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Sqlite/SqliteConnectionStringChecker.cs
new file mode 100644
index 000000000..747309900
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.DbChecker/LINGYUN/Abp/Saas/Sqlite/SqliteConnectionStringChecker.cs
@@ -0,0 +1,33 @@
+using LINGYUN.Abp.Saas.Tenants;
+using Microsoft.Data.Sqlite;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.Saas.Sqlite;
+
+public class SqliteConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency
+{
+ public virtual async Task CheckAsync(string connectionString)
+ {
+ var result = new DataBaseConnectionStringCheckResult();
+
+ try
+ {
+ await using var conn = new SqliteConnection(connectionString);
+ await conn.OpenAsync();
+ result.Connected = true;
+ result.DatabaseExists = true;
+
+ await conn.CloseAsync();
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ result.Error = e;
+ return result;
+ }
+ }
+}
+
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs
index ed946d9a7..4103cbb9c 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs
@@ -20,7 +20,7 @@ public static class AbpSaasErrorCodes
///
public const string TenantIdOrNameNotFound = Namespace + ":020002";
///
- /// 无效的默认连接字符串
+ /// 无法打开默认连接字符串指向的数据库连接
///
public const string InvalidDefaultConnectionString = Namespace + ":020101";
///
@@ -31,4 +31,8 @@ public static class AbpSaasErrorCodes
/// {Name} 的连接字符串无效
///
public const string InvalidConnectionString = Namespace + ":020103";
+ ///
+ /// 不支持 {Name} 类型的数据库连接检查
+ ///
+ public const string ConnectionStringProviderNotSupport = Namespace + ":020104";
}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json
index 8d13828e7..8d976749b 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json
@@ -8,6 +8,7 @@
"Saas:020101": "The default connection string cannot open a connection to the database!",
"Saas:020102": "The database pointed to by the default connection string already exists!",
"Saas:020103": "Unable to open the database connection pointed to by {Name}!",
+ "Saas:020104": "Database connection check of the {Name} type is not supported!",
"Volo.AbpIo.MultiTenancy:010001": "The tenant is unavailable or restricted!",
"Volo.AbpIo.MultiTenancy:010002": "Tenant unavailable!",
"Menu:Saas": "Saas",
@@ -25,6 +26,7 @@
"ConnectionStrings:AddNew": "New Connection",
"DisplayName:DefaultConnectionString": "Default Connection String",
"DisplayName:UseSharedDatabase": "Use the Shared Database",
+ "DisplayName:DataBaseProvider": "Data Base Provider",
"DisplayName:Name": "Name",
"DisplayName:Value": "Value",
"DisplayName:IsActive": "Active",
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json
index 26caa8a45..21dba4be6 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json
@@ -8,6 +8,7 @@
"Saas:020101": "无法打开默认连接字符串指向的数据库连接!",
"Saas:020102": "默认连接字符串指向的数据库已经存在!",
"Saas:020103": "无法打开 {Name} 指向的数据库连接!",
+ "Saas:020104": "不支持 {Name} 类型的数据库连接检查!",
"Volo.AbpIo.MultiTenancy:010001": "租户不可用或受限制!",
"Volo.AbpIo.MultiTenancy:010002": "租户不可用!",
"Menu:Saas": "Saas",
@@ -25,6 +26,7 @@
"ConnectionStrings:AddNew": "添加新连接",
"DisplayName:DefaultConnectionString": "默认连接字符串",
"DisplayName:UseSharedDatabase": "使用共享数据库",
+ "DisplayName:DataBaseProvider": "数据库提供者",
"DisplayName:Name": "名称",
"DisplayName:Value": "值",
"DisplayName:IsActive": "启用",
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/AbpSaasConnectionStringCheckOptions.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/AbpSaasConnectionStringCheckOptions.cs
new file mode 100644
index 000000000..10c287eb9
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/AbpSaasConnectionStringCheckOptions.cs
@@ -0,0 +1,15 @@
+using LINGYUN.Abp.Saas.Tenants;
+using System;
+using System.Collections.Generic;
+
+namespace LINGYUN.Abp.Saas;
+
+public class AbpSaasConnectionStringCheckOptions
+{
+ public IDictionary ConnectionStringCheckers { get; }
+
+ public AbpSaasConnectionStringCheckOptions()
+ {
+ ConnectionStringCheckers = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/DataBaseConnectionStringCheckResult.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/DataBaseConnectionStringCheckResult.cs
new file mode 100644
index 000000000..e79456841
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/DataBaseConnectionStringCheckResult.cs
@@ -0,0 +1,9 @@
+using System;
+using Volo.Abp.Data;
+
+namespace LINGYUN.Abp.Saas.Tenants;
+
+public class DataBaseConnectionStringCheckResult : AbpConnectionStringCheckResult
+{
+ public Exception Error { get; set; }
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/IDataBaseConnectionStringChecker.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/IDataBaseConnectionStringChecker.cs
new file mode 100644
index 000000000..f2ce72c51
--- /dev/null
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/IDataBaseConnectionStringChecker.cs
@@ -0,0 +1,8 @@
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Saas.Tenants;
+
+public interface IDataBaseConnectionStringChecker
+{
+ Task CheckAsync(string connectionString);
+}
diff --git a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.HttpApi/LINGYUN/Abp/Saas/Tenants/TenantController.cs b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.HttpApi/LINGYUN/Abp/Saas/Tenants/TenantController.cs
index 9e29feaa9..34120729a 100644
--- a/aspnet-core/modules/saas/LINGYUN.Abp.Saas.HttpApi/LINGYUN/Abp/Saas/Tenants/TenantController.cs
+++ b/aspnet-core/modules/saas/LINGYUN.Abp.Saas.HttpApi/LINGYUN/Abp/Saas/Tenants/TenantController.cs
@@ -95,4 +95,11 @@ public class TenantController : AbpSaasControllerBase, ITenantAppService
{
return TenantAppService.DeleteConnectionStringAsync(id, name);
}
+ [HttpPost]
+ [Route("connection-string/check")]
+ [Authorize(AbpSaasPermissions.Tenants.ManageConnectionStrings)]
+ public virtual Task CheckConnectionStringAsync(TenantConnectionStringCheckInput input)
+ {
+ return TenantAppService.CheckConnectionStringAsync(input);
+ }
}
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xml b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xsd b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xsd
new file mode 100644
index 000000000..3f3946e28
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj
new file mode 100644
index 000000000..7f15d10c2
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ netstandard2.0;netstandard2.1;net8.0;net9.0
+ LINGYUN.Abp.Quartz.MySqlInstaller
+ LINGYUN.Abp.Quartz.MySqlInstaller
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/AbpQuartzMySqlInstallerModule.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/AbpQuartzMySqlInstallerModule.cs
new file mode 100644
index 000000000..94b8e0422
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/AbpQuartzMySqlInstallerModule.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Modularity;
+using Volo.Abp.Quartz;
+using Volo.Abp.VirtualFileSystem;
+
+namespace LINGYUN.Abp.Quartz.MySqlInstaller;
+
+[DependsOn(
+ typeof(AbpQuartzModule),
+ typeof(AbpVirtualFileSystemModule))]
+public class AbpQuartzMySqlInstallerModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+ }
+
+ public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
+ {
+ var configuration = context.ServiceProvider.GetRequiredService();
+ if (configuration.GetValue("Quartz:UsePersistentStore", false))
+ {
+ // 初始化 Quartz Mysql 数据库
+ await context.ServiceProvider
+ .GetRequiredService()
+ .InstallAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/QuartzMySqlInstaller.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/QuartzMySqlInstaller.cs
new file mode 100644
index 000000000..5358d43da
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/QuartzMySqlInstaller.cs
@@ -0,0 +1,137 @@
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+using System;
+using System.Data;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Quartz;
+using Volo.Abp.VirtualFileSystem;
+using static Quartz.SchedulerBuilder;
+
+namespace LINGYUN.Abp.Quartz.MySqlInstaller;
+
+public class QuartzMySqlInstaller : ITransientDependency
+{
+ public ILogger Logger { protected get; set; }
+
+ private readonly IVirtualFileProvider _virtualFileProvider;
+ private readonly AbpQuartzOptions _quartzOptions;
+
+ public QuartzMySqlInstaller(
+ IVirtualFileProvider virtualFileProvider,
+ IOptions quartzOptions)
+ {
+ _quartzOptions = quartzOptions.Value;
+ _virtualFileProvider = virtualFileProvider;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async virtual Task InstallAsync()
+ {
+ var dataSource = _quartzOptions.Properties["quartz.jobStore.dataSource"] ?? AdoProviderOptions.DefaultDataSourceName;
+ var connectionString = _quartzOptions.Properties[$"quartz.dataSource.{dataSource}.connectionString"];
+ var tablePrefix = _quartzOptions.Properties["quartz.jobStore.tablePrefix"] ?? "QRTZ_";
+
+ if (connectionString.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning($"Please configure the `{dataSource}` database connection string in `quartz.jobStore.dataSource`!");
+ throw new ArgumentNullException(nameof(connectionString));
+ }
+
+ Logger.LogInformation("Install Quartz MySql...");
+
+ var builder = new MySqlConnectionStringBuilder(connectionString);
+
+ var dataBaseName = await CreateDataBaseIfNotExists(builder.Database, builder);
+
+ builder.Database = dataBaseName;
+
+ using var mySqlConnection = new MySqlConnection(builder.ConnectionString);
+
+ if (mySqlConnection.State == ConnectionState.Closed)
+ {
+ await mySqlConnection.OpenAsync();
+ }
+
+ using (var mySqlCommand = new MySqlCommand("SELECT COUNT(1) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = @DataBaseName;", mySqlConnection))
+ {
+ mySqlCommand.Parameters.Add("@DataBaseName", MySqlDbType.String).Value = dataBaseName;
+
+ var rowsAffects = await mySqlCommand.ExecuteScalarAsync() as long?;
+ if (rowsAffects > 0)
+ {
+ Logger.LogInformation($"The `{dataBaseName}` tables has already exists.");
+ return;
+ }
+ }
+
+ var sqlScript = await GetInitSqlScript();
+
+ // USE `${DataBase}` -> USE `Workflow`;
+ sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName);
+ // CREATE TABLE $(TablePrefix)JOB_DETAILS` -> CREATE TABLE QRTZ_JOB_DETAILS;
+ sqlScript = sqlScript.Replace("${TablePrefix}", tablePrefix);
+
+ using (var mySqlCommand = new MySqlCommand(sqlScript, mySqlConnection))
+ {
+ Logger.LogInformation("The database initialization script `Initial.sql` starts...");
+
+ await mySqlCommand.ExecuteNonQueryAsync();
+ }
+
+ Logger.LogInformation("Database initialization script `Initial.sql` complete!");
+ }
+
+ public async virtual Task CreateDataBaseIfNotExists(string dataBase, MySqlConnectionStringBuilder connectionStringBuilder)
+ {
+ // 切换主数据库查询数据库是否存在
+ connectionStringBuilder.Database = "mysql";
+ using var mySqlConnection = new MySqlConnection(connectionStringBuilder.ConnectionString);
+ if (mySqlConnection.State == ConnectionState.Closed)
+ {
+ await mySqlConnection.OpenAsync();
+ }
+
+ var checkDataBaseName = "";
+ using (var mySqlCommand = new MySqlCommand("SELECT `SCHEMA_NAME` FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME` = @DataBaseName;", mySqlConnection))
+ {
+ var dataBaseParamter = mySqlCommand.Parameters.Add("DataBaseName", DbType.String);
+ dataBaseParamter.Value = dataBase;
+
+ checkDataBaseName = await mySqlCommand.ExecuteScalarAsync() as string;
+ }
+
+ if (checkDataBaseName.IsNullOrWhiteSpace())
+ {
+ using (var mySqlCommand = new MySqlCommand($"CREATE DATABASE `{dataBase}` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';", mySqlConnection))
+ {
+ await mySqlCommand.ExecuteNonQueryAsync();
+ }
+ }
+
+ return dataBase;
+ }
+
+ public async virtual Task GetInitSqlScript()
+ {
+ var sqlScriptFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql");
+ if (!sqlScriptFileInfo.Exists || sqlScriptFileInfo.IsDirectory)
+ {
+ Logger.LogWarning("Please Check that the `Initial.sql` file exists!");
+ throw new InvalidOperationException("The `Initial.sql` database initialization script file does not exist or is not valid!");
+ }
+
+ var sqlScript = await sqlScriptFileInfo.ReadAsStringAsync();
+ if (sqlScript.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning("The contents of the `Initial.sql` file are empty or invalid!");
+ throw new InvalidOperationException("The contents of the `Initial.sql` file are empty or invalid!");
+ }
+
+ return sqlScript;
+ }
+}
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql
new file mode 100644
index 000000000..85a70bfff
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql
@@ -0,0 +1,181 @@
+# By: Ron Cordell - roncordell
+# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
+
+
+# make sure you have UTF-8 collaction for best .NET interoperability
+# CREATE DATABASE quartznet CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+USE `${DataBase}`;
+
+DROP TABLE IF EXISTS ${TablePrefix}FIRED_TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS ${TablePrefix}SCHEDULER_STATE;
+DROP TABLE IF EXISTS ${TablePrefix}LOCKS;
+DROP TABLE IF EXISTS ${TablePrefix}SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}CRON_TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}BLOB_TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}TRIGGERS;
+DROP TABLE IF EXISTS ${TablePrefix}JOB_DETAILS;
+DROP TABLE IF EXISTS ${TablePrefix}CALENDARS;
+
+CREATE TABLE ${TablePrefix}JOB_DETAILS(
+SCHED_NAME VARCHAR(120) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+JOB_CLASS_NAME VARCHAR(250) NOT NULL,
+IS_DURABLE BOOLEAN NOT NULL,
+IS_NONCONCURRENT BOOLEAN NOT NULL,
+IS_UPDATE_DATA BOOLEAN NOT NULL,
+REQUESTS_RECOVERY BOOLEAN NOT NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+NEXT_FIRE_TIME BIGINT(19) NULL,
+PREV_FIRE_TIME BIGINT(19) NULL,
+PRIORITY INTEGER NULL,
+TRIGGER_STATE VARCHAR(16) NOT NULL,
+TRIGGER_TYPE VARCHAR(8) NOT NULL,
+START_TIME BIGINT(19) NOT NULL,
+END_TIME BIGINT(19) NULL,
+CALENDAR_NAME VARCHAR(200) NULL,
+MISFIRE_INSTR SMALLINT(2) NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+REFERENCES ${TablePrefix}JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}SIMPLE_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+REPEAT_COUNT BIGINT(7) NOT NULL,
+REPEAT_INTERVAL BIGINT(12) NOT NULL,
+TIMES_TRIGGERED BIGINT(10) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}CRON_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+CRON_EXPRESSION VARCHAR(120) NOT NULL,
+TIME_ZONE_ID VARCHAR(80),
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}SIMPROP_TRIGGERS
+ (
+ SCHED_NAME VARCHAR(120) NOT NULL,
+ TRIGGER_NAME VARCHAR(200) NOT NULL,
+ TRIGGER_GROUP VARCHAR(200) NOT NULL,
+ STR_PROP_1 VARCHAR(512) NULL,
+ STR_PROP_2 VARCHAR(512) NULL,
+ STR_PROP_3 VARCHAR(512) NULL,
+ INT_PROP_1 INT NULL,
+ INT_PROP_2 INT NULL,
+ LONG_PROP_1 BIGINT NULL,
+ LONG_PROP_2 BIGINT NULL,
+ DEC_PROP_1 NUMERIC(13,4) NULL,
+ DEC_PROP_2 NUMERIC(13,4) NULL,
+ BOOL_PROP_1 BOOLEAN NULL,
+ BOOL_PROP_2 BOOLEAN NULL,
+ TIME_ZONE_ID VARCHAR(80) NULL,
+ PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+ FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+ REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}BLOB_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+BLOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}CALENDARS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+CALENDAR_NAME VARCHAR(200) NOT NULL,
+CALENDAR BLOB NOT NULL,
+PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}PAUSED_TRIGGER_GRPS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}FIRED_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+ENTRY_ID VARCHAR(140) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+FIRED_TIME BIGINT(19) NOT NULL,
+SCHED_TIME BIGINT(19) NOT NULL,
+PRIORITY INTEGER NOT NULL,
+STATE VARCHAR(16) NOT NULL,
+JOB_NAME VARCHAR(200) NULL,
+JOB_GROUP VARCHAR(200) NULL,
+IS_NONCONCURRENT BOOLEAN NULL,
+REQUESTS_RECOVERY BOOLEAN NULL,
+PRIMARY KEY (SCHED_NAME,ENTRY_ID))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}SCHEDULER_STATE (
+SCHED_NAME VARCHAR(120) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+LAST_CHECKIN_TIME BIGINT(19) NOT NULL,
+CHECKIN_INTERVAL BIGINT(19) NOT NULL,
+PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE ${TablePrefix}LOCKS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+LOCK_NAME VARCHAR(40) NOT NULL,
+PRIMARY KEY (SCHED_NAME,LOCK_NAME))
+ENGINE=InnoDB;
+
+CREATE INDEX IDX_${TablePrefix}J_REQ_RECOVERY ON ${TablePrefix}JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_${TablePrefix}J_GRP ON ${TablePrefix}JOB_DETAILS(SCHED_NAME,JOB_GROUP);
+
+CREATE INDEX IDX_${TablePrefix}T_J ON ${TablePrefix}TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_${TablePrefix}T_JG ON ${TablePrefix}TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_${TablePrefix}T_C ON ${TablePrefix}TRIGGERS(SCHED_NAME,CALENDAR_NAME);
+CREATE INDEX IDX_${TablePrefix}T_G ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_${TablePrefix}T_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_STATE);
+CREATE INDEX IDX_${TablePrefix}T_N_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_${TablePrefix}T_N_G_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_${TablePrefix}T_NEXT_FIRE_TIME ON ${TablePrefix}TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
+CREATE INDEX IDX_${TablePrefix}T_NFT_ST ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+CREATE INDEX IDX_${TablePrefix}T_NFT_MISFIRE ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+CREATE INDEX IDX_${TablePrefix}T_NFT_ST_MISFIRE ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+CREATE INDEX IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+CREATE INDEX IDX_${TablePrefix}FT_TRIG_INST_NAME ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
+CREATE INDEX IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_${TablePrefix}FT_J_G ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_${TablePrefix}FT_JG ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_${TablePrefix}FT_T_G ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_${TablePrefix}FT_TG ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+
+commit;
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/FodyWeavers.xml b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN.Abp.Quartz.SqlServerInstaller.csproj b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN.Abp.Quartz.SqlServerInstaller.csproj
new file mode 100644
index 000000000..e8ae8b21b
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN.Abp.Quartz.SqlServerInstaller.csproj
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ netstandard2.0;netstandard2.1;net8.0;net9.0
+ LINGYUN.Abp.Quartz.SqlServerInstaller
+ LINGYUN.Abp.Quartz.SqlServerInstaller
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/AbpQuartzSqlServerInstallerModule.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/AbpQuartzSqlServerInstallerModule.cs
new file mode 100644
index 000000000..0e8eabe51
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/AbpQuartzSqlServerInstallerModule.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Modularity;
+using Volo.Abp.Quartz;
+using Volo.Abp.VirtualFileSystem;
+
+namespace LINGYUN.Abp.Quartz.SqlServerInstaller;
+
+[DependsOn(
+ typeof(AbpQuartzModule),
+ typeof(AbpVirtualFileSystemModule))]
+public class AbpQuartzSqlServerInstallerModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+ }
+
+ public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
+ {
+ var configuration = context.ServiceProvider.GetRequiredService();
+ if (configuration.GetValue("Quartz:UsePersistentStore", false))
+ {
+ // 初始化 Quartz SqlServer 数据库
+ await context.ServiceProvider
+ .GetRequiredService()
+ .InstallAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/QuartzSqlServerInstaller.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/QuartzSqlServerInstaller.cs
new file mode 100644
index 000000000..ec2d3460e
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/QuartzSqlServerInstaller.cs
@@ -0,0 +1,137 @@
+using Microsoft.Data.SqlClient;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using System;
+using System.Data;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Quartz;
+using Volo.Abp.VirtualFileSystem;
+using static Quartz.SchedulerBuilder;
+
+namespace LINGYUN.Abp.Quartz.SqlServerInstaller;
+
+public class QuartzSqlServerInstaller : ITransientDependency
+{
+ public ILogger Logger { protected get; set; }
+
+ private readonly IVirtualFileProvider _virtualFileProvider;
+ private readonly AbpQuartzOptions _quartzOptions;
+
+ public QuartzSqlServerInstaller(
+ IVirtualFileProvider virtualFileProvider,
+ IOptions quartzOptions)
+ {
+ _quartzOptions = quartzOptions.Value;
+ _virtualFileProvider = virtualFileProvider;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async virtual Task InstallAsync()
+ {
+ var dataSource = _quartzOptions.Properties["quartz.jobStore.dataSource"] ?? AdoProviderOptions.DefaultDataSourceName;
+ var connectionString = _quartzOptions.Properties[$"quartz.dataSource.{dataSource}.connectionString"];
+ var tablePrefix = _quartzOptions.Properties["quartz.jobStore.tablePrefix"] ?? "QRTZ_";
+
+ if (connectionString.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning($"Please configure the `{dataSource}` database connection string in `quartz.jobStore.dataSource`!");
+ throw new ArgumentNullException(nameof(connectionString));
+ }
+
+ Logger.LogInformation("Install Quartz SqlServer...");
+
+ var builder = new SqlConnectionStringBuilder(connectionString);
+
+ var dataBaseName = await CreateDataBaseIfNotExists(builder.InitialCatalog, builder);
+
+ builder.InitialCatalog = dataBaseName;
+
+ using var sqlConnection = new SqlConnection(builder.ConnectionString);
+
+ if (sqlConnection.State == ConnectionState.Closed)
+ {
+ await sqlConnection.OpenAsync();
+ }
+
+ using (var sqlCommand = new SqlCommand("SELECT COUNT(1) FROM [sys].[objects] WHERE type=N'U'", sqlConnection))
+ {
+ sqlCommand.Parameters.Add("@DataBaseName", SqlDbType.NVarChar).Value = dataBaseName;
+
+ var rowsAffects = await sqlCommand.ExecuteScalarAsync() as long?;
+ if (rowsAffects > 0)
+ {
+ Logger.LogInformation($"The `{dataBaseName}` tables has already exists.");
+ return;
+ }
+ }
+
+ var sqlScript = await GetInitSqlScript();
+
+ // USE `${DataBase}` -> USE `Workflow`;
+ sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName);
+ // CREATE TABLE $(TablePrefix)JOB_DETAILS` -> CREATE TABLE QRTZ_JOB_DETAILS;
+ sqlScript = sqlScript.Replace("${TablePrefix}", tablePrefix);
+
+ using (var sqlCommand = new SqlCommand(sqlScript, sqlConnection))
+ {
+ Logger.LogInformation("The database initialization script `Initial.sql` starts...");
+
+ await sqlCommand.ExecuteNonQueryAsync();
+ }
+
+ Logger.LogInformation("Database initialization script `Initial.sql` complete!");
+ }
+
+ public async virtual Task CreateDataBaseIfNotExists(string dataBase, SqlConnectionStringBuilder connectionStringBuilder)
+ {
+ // 切换主数据库查询数据库是否存在
+ connectionStringBuilder.InitialCatalog = "master";
+ using var sqlConnection = new SqlConnection(connectionStringBuilder.ConnectionString);
+ if (sqlConnection.State == ConnectionState.Closed)
+ {
+ await sqlConnection.OpenAsync();
+ }
+
+ var checkDataBaseName = "";
+ using (var sqlCommand = new SqlCommand("SELECT [name] FROM [master].[dbo].[sysdatabases] WHERE [name] = @DataBaseName;", sqlConnection))
+ {
+ var dataBaseParamter = sqlCommand.Parameters.Add("DataBaseName", SqlDbType.NVarChar);
+ dataBaseParamter.Value = dataBase;
+
+ checkDataBaseName = await sqlCommand.ExecuteScalarAsync() as string;
+ }
+
+ if (checkDataBaseName.IsNullOrWhiteSpace())
+ {
+ using (var sqlCommand = new SqlCommand($"CREATE DATABASE {dataBase};", sqlConnection))
+ {
+ await sqlCommand.ExecuteNonQueryAsync();
+ }
+ }
+
+ return dataBase;
+ }
+
+ public async virtual Task GetInitSqlScript()
+ {
+ var sqlScriptFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql");
+ if (!sqlScriptFileInfo.Exists || sqlScriptFileInfo.IsDirectory)
+ {
+ Logger.LogWarning("Please Check that the `Initial.sql` file exists!");
+ throw new InvalidOperationException("The `Initial.sql` database initialization script file does not exist or is not valid!");
+ }
+
+ var sqlScript = await sqlScriptFileInfo.ReadAsStringAsync();
+ if (sqlScript.IsNullOrWhiteSpace())
+ {
+ Logger.LogWarning("The contents of the `Initial.sql` file are empty or invalid!");
+ throw new InvalidOperationException("The contents of the `Initial.sql` file are empty or invalid!");
+ }
+
+ return sqlScript;
+ }
+}
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql
new file mode 100644
index 000000000..5c4478d7d
--- /dev/null
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql
@@ -0,0 +1,370 @@
+-- this script is for SQL Server and Azure SQL
+
+-- This initializes the database to pristine for Quartz, by first removing any existing Quartz tables
+-- and then recreating them from scratch.
+-- Should you only require it to create the tables, set @DropDb to 0.
+
+USE [${DataBase}];
+GO
+
+DECLARE @DropDb BIT = 1; -- Set this to 0 to skip DROP statements, 1 to include them
+
+IF @DropDb = 1
+BEGIN
+ -- drop indexes if they exist and rebuild if current ones
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_J] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_JG] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_C] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_G] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_G_J] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_N_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_N_G_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NEXT_FIRE_TIME] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP] ON [dbo].[${TablePrefix}TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_TRIG_INST_NAME] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_J_G] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_JG] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_T_G] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_TG] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_G_J] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+ DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_G_T] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS]', N'F') IS NOT NULL
+ ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS];
+
+ IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
+ ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
+ ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
+ ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS];
+
+ IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_${TablePrefix}JOB_LISTENERS_${TablePrefix}JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[${TablePrefix}JOB_LISTENERS]'))
+ ALTER TABLE [dbo].[${TablePrefix}JOB_LISTENERS] DROP CONSTRAINT [FK_${TablePrefix}JOB_LISTENERS_${TablePrefix}JOB_DETAILS];
+
+ IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_${TablePrefix}TRIGGER_LISTENERS_${TablePrefix}TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGER_LISTENERS]'))
+ ALTER TABLE [dbo].[${TablePrefix}TRIGGER_LISTENERS] DROP CONSTRAINT [FK_${TablePrefix}TRIGGER_LISTENERS_${TablePrefix}TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}CALENDARS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}CALENDARS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}CRON_TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}CRON_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}BLOB_TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}FIRED_TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}JOB_LISTENERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}JOB_LISTENERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}SCHEDULER_STATE]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}SCHEDULER_STATE];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}LOCKS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}LOCKS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGER_LISTENERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}TRIGGER_LISTENERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}JOB_DETAILS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}JOB_DETAILS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}SIMPLE_TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}SIMPROP_TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS];
+
+ IF OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGERS]', N'U') IS NOT NULL
+ DROP TABLE [dbo].[${TablePrefix}TRIGGERS];
+END
+
+CREATE TABLE [dbo].[${TablePrefix}CALENDARS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [CALENDAR_NAME] nvarchar(200) NOT NULL,
+ [CALENDAR] varbinary(max) NOT NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [CRON_EXPRESSION] nvarchar(120) NOT NULL,
+ [TIME_ZONE_ID] nvarchar(80)
+);
+
+CREATE TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [ENTRY_ID] nvarchar(140) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [INSTANCE_NAME] nvarchar(200) NOT NULL,
+ [FIRED_TIME] bigint NOT NULL,
+ [SCHED_TIME] bigint NOT NULL,
+ [PRIORITY] int NOT NULL,
+ [STATE] nvarchar(16) NOT NULL,
+ [JOB_NAME] nvarchar(150) NULL,
+ [JOB_GROUP] nvarchar(150) NULL,
+ [IS_NONCONCURRENT] bit NULL,
+ [REQUESTS_RECOVERY] bit NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}SCHEDULER_STATE] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [INSTANCE_NAME] nvarchar(200) NOT NULL,
+ [LAST_CHECKIN_TIME] bigint NOT NULL,
+ [CHECKIN_INTERVAL] bigint NOT NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}LOCKS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [LOCK_NAME] nvarchar(40) NOT NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}JOB_DETAILS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [JOB_NAME] nvarchar(150) NOT NULL,
+ [JOB_GROUP] nvarchar(150) NOT NULL,
+ [DESCRIPTION] nvarchar(250) NULL,
+ [JOB_CLASS_NAME] nvarchar(250) NOT NULL,
+ [IS_DURABLE] bit NOT NULL,
+ [IS_NONCONCURRENT] bit NOT NULL,
+ [IS_UPDATE_DATA] bit NOT NULL,
+ [REQUESTS_RECOVERY] bit NOT NULL,
+ [JOB_DATA] varbinary(max) NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [REPEAT_COUNT] int NOT NULL,
+ [REPEAT_INTERVAL] bigint NOT NULL,
+ [TIMES_TRIGGERED] int NOT NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [STR_PROP_1] nvarchar(512) NULL,
+ [STR_PROP_2] nvarchar(512) NULL,
+ [STR_PROP_3] nvarchar(512) NULL,
+ [INT_PROP_1] int NULL,
+ [INT_PROP_2] int NULL,
+ [LONG_PROP_1] bigint NULL,
+ [LONG_PROP_2] bigint NULL,
+ [DEC_PROP_1] numeric(13,4) NULL,
+ [DEC_PROP_2] numeric(13,4) NULL,
+ [BOOL_PROP_1] bit NULL,
+ [BOOL_PROP_2] bit NULL,
+ [TIME_ZONE_ID] nvarchar(80) NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [BLOB_DATA] varbinary(max) NULL
+);
+
+CREATE TABLE [dbo].[${TablePrefix}TRIGGERS] (
+ [SCHED_NAME] nvarchar(120) NOT NULL,
+ [TRIGGER_NAME] nvarchar(150) NOT NULL,
+ [TRIGGER_GROUP] nvarchar(150) NOT NULL,
+ [JOB_NAME] nvarchar(150) NOT NULL,
+ [JOB_GROUP] nvarchar(150) NOT NULL,
+ [DESCRIPTION] nvarchar(250) NULL,
+ [NEXT_FIRE_TIME] bigint NULL,
+ [PREV_FIRE_TIME] bigint NULL,
+ [PRIORITY] int NULL,
+ [TRIGGER_STATE] nvarchar(16) NOT NULL,
+ [TRIGGER_TYPE] nvarchar(8) NOT NULL,
+ [START_TIME] bigint NOT NULL,
+ [END_TIME] bigint NULL,
+ [CALENDAR_NAME] nvarchar(200) NULL,
+ [MISFIRE_INSTR] int NULL,
+ [JOB_DATA] varbinary(max) NULL
+);
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}CALENDARS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}CALENDARS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [CALENDAR_NAME]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}CRON_TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}FIRED_TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [ENTRY_ID]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}SCHEDULER_STATE] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}SCHEDULER_STATE] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [INSTANCE_NAME]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}LOCKS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}LOCKS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [LOCK_NAME]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}JOB_DETAILS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}JOB_DETAILS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [JOB_NAME],
+ [JOB_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS] WITH NOCHECK ADD
+ CONSTRAINT [PK_${TablePrefix}BLOB_TRIGGERS] PRIMARY KEY CLUSTERED
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ );
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] ADD
+ CONSTRAINT [FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) ON DELETE CASCADE;
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] ADD
+ CONSTRAINT [FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) ON DELETE CASCADE;
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] ADD
+ CONSTRAINT [FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
+ (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
+ [SCHED_NAME],
+ [TRIGGER_NAME],
+ [TRIGGER_GROUP]
+ ) ON DELETE CASCADE;
+GO
+
+ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] ADD
+ CONSTRAINT [FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS] FOREIGN KEY
+ (
+ [SCHED_NAME],
+ [JOB_NAME],
+ [JOB_GROUP]
+ ) REFERENCES [dbo].[${TablePrefix}JOB_DETAILS] (
+ [SCHED_NAME],
+ [JOB_NAME],
+ [JOB_GROUP]
+ );
+GO
+
+-- Create indexes
+CREATE INDEX [IDX_${TablePrefix}T_G_J] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, JOB_GROUP, JOB_NAME);
+CREATE INDEX [IDX_${TablePrefix}T_C] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, CALENDAR_NAME);
+
+CREATE INDEX [IDX_${TablePrefix}T_N_G_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE);
+CREATE INDEX [IDX_${TablePrefix}T_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_STATE);
+CREATE INDEX [IDX_${TablePrefix}T_N_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE);
+CREATE INDEX [IDX_${TablePrefix}T_NEXT_FIRE_TIME] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, NEXT_FIRE_TIME);
+CREATE INDEX [IDX_${TablePrefix}T_NFT_ST] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME);
+CREATE INDEX [IDX_${TablePrefix}T_NFT_ST_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE);
+CREATE INDEX [IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE);
+
+CREATE INDEX [IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY);
+CREATE INDEX [IDX_${TablePrefix}FT_G_J] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, JOB_GROUP, JOB_NAME);
+CREATE INDEX [IDX_${TablePrefix}FT_G_T] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, TRIGGER_GROUP, TRIGGER_NAME);
+GO
\ No newline at end of file
diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
index 80aaa954c..454b776f8 100644
--- a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
+++ b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
@@ -15,7 +15,6 @@
-
@@ -231,6 +230,7 @@
+
@@ -247,6 +247,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
index 708f3e411..7da8941fe 100644
--- a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
+++ b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
@@ -2,6 +2,7 @@ using LINGYUN.Abp.Identity.WeChat.Work;
using LINGYUN.Abp.Notifications.Templating;
using LINGYUN.Abp.Notifications.WeChat.Work;
using LINGYUN.Abp.OssManagement.Minio;
+using LINGYUN.Abp.Quartz.MySqlInstaller;
namespace LY.MicroService.Applications.Single;
@@ -162,6 +163,8 @@ namespace LY.MicroService.Applications.Single;
typeof(AbpSaasHttpApiModule),
// Saas模块 实体框架
typeof(AbpSaasEntityFrameworkCoreModule),
+ // Saas模块 数据库连接检查
+ typeof(AbpSaasDbCheckerModule),
// 任务管理模块 领域服务
typeof(TaskManagementDomainModule),
@@ -262,6 +265,8 @@ namespace LY.MicroService.Applications.Single;
typeof(AbpBackgroundTasksNotificationsModule),
// 后台任务模块 Quartz集成
typeof(AbpBackgroundTasksQuartzModule),
+ // Quartz MySql数据库初始化模块
+ typeof(AbpQuartzMySqlInstallerModule),
// 数据审计模块 应用服务
typeof(AbpDataProtectionManagementApplicationModule),
diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/LY.MicroService.TaskManagement.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/LY.MicroService.TaskManagement.HttpApi.Host.csproj
index 3443f8310..913a312df 100644
--- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/LY.MicroService.TaskManagement.HttpApi.Host.csproj
+++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/LY.MicroService.TaskManagement.HttpApi.Host.csproj
@@ -66,6 +66,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs
index b8f6b51f7..6af1ef7f3 100644
--- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs
+++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs
@@ -16,6 +16,7 @@ using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.OssManagement;
+using LINGYUN.Abp.Quartz.MySqlInstaller;
using LINGYUN.Abp.Saas.EntityFrameworkCore;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
@@ -63,6 +64,7 @@ namespace LY.MicroService.TaskManagement;
typeof(AbpBackgroundTasksDistributedLockingModule),
typeof(AbpBackgroundTasksExceptionHandlingModule),
typeof(AbpBackgroundTasksNotificationsModule),
+ typeof(AbpQuartzMySqlInstallerModule),
typeof(TaskManagementApplicationModule),
typeof(TaskManagementHttpApiModule),
typeof(TaskManagementEntityFrameworkCoreModule),
diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj
index a0e53d6b0..39ecc0cca 100644
--- a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj
+++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj
@@ -60,6 +60,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs
index 68191fb9e..16ba651bd 100644
--- a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs
+++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs
@@ -14,6 +14,7 @@ using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Http.Client.Wrapper;
using LINGYUN.Abp.Identity.Session.AspNetCore;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
+using LINGYUN.Abp.Quartz.MySqlInstaller;
using LINGYUN.Abp.Saas.EntityFrameworkCore;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
@@ -60,6 +61,7 @@ namespace LY.MicroService.WebhooksManagement;
typeof(AbpBackgroundTasksQuartzModule),
typeof(AbpBackgroundTasksDistributedLockingModule),
typeof(AbpBackgroundTasksExceptionHandlingModule),
+ typeof(AbpQuartzMySqlInstallerModule),
typeof(TaskManagementEntityFrameworkCoreModule),
typeof(AbpSaasEntityFrameworkCoreModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj
index f4e5be3ca..d38cfddea 100644
--- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj
+++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj
@@ -76,6 +76,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs
index d9b3a7116..578889b52 100644
--- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs
+++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs
@@ -20,6 +20,7 @@ using LINGYUN.Abp.Http.Client.Wrapper;
using LINGYUN.Abp.Identity.Session.AspNetCore;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
+using LINGYUN.Abp.Quartz.MySqlInstaller;
using LINGYUN.Abp.Saas.EntityFrameworkCore;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
@@ -66,6 +67,7 @@ namespace LY.MicroService.WorkflowManagement;
typeof(AbpBackgroundTasksQuartzModule),
typeof(AbpBackgroundTasksDistributedLockingModule),
typeof(AbpBackgroundTasksExceptionHandlingModule),
+ typeof(AbpQuartzMySqlInstallerModule),
typeof(TaskManagementEntityFrameworkCoreModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),