From 6c0d1ea66c34f482252851d4cc8b80181f0148f1 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 31 Jan 2025 19:51:24 +0100 Subject: [PATCH] Refactor database setup and EFCore provider configurations. Revised database initialization scripts to better handle Postgres and Oracle environments, introduced schema-specific configurations for Oracle EFCore, and cleaned up obsolete or redundant entity model setup. Streamlined project structure by relocating and renaming files for SQLite and Oracle EFCore setups, improving maintainability and readability. --- Elsa.sln | 8 +++- docker/docker-compose.yml | 9 ++-- docker/{init-db.sh => init-db-postgres.sh} | 0 docker/oracle-setup/setup.sql | 3 ++ src/apps/Elsa.Server.Web/Program.cs | 11 ++--- src/apps/Elsa.Server.Web/appsettings.json | 2 +- .../Feature.cs | 1 - .../SetupForOracle.cs | 25 ----------- .../CommonPersistenceFeature.cs | 1 - .../DbSchemaAwareMigrationAssembly.cs | 17 ++++---- .../Elsa.EntityFrameworkCore.Common.csproj | 1 - .../ElsaDbContextBase.cs | 4 +- .../PersistenceFeatureBase.cs | 9 ++-- .../Alterations/20241212211620_V3_3.cs | 2 +- .../Identity/20241212211936_V3_3.cs | 2 +- .../Migrations/Labels/20241212212100_V3_3.cs | 2 +- .../Management/20241212211817_V3_3.cs | 2 +- .../Migrations/Runtime/20250116193207_V3_3.cs | 2 +- .../Migrations/Tenants/20241212212227_V3_3.cs | 2 +- .../OracleProvidersExtensions.cs | 41 +++++++++++-------- .../SetupForAlterations.cs} | 5 +-- .../SetupForManagement.cs | 39 ++++++++++++++++++ .../SetupForRuntime.cs} | 5 +-- .../SetupForSqlite.cs | 2 +- .../SqliteProvidersExtensions.cs | 6 ++- .../Modules/Alterations/Feature.cs | 1 - .../Modules/Management/SetupForOracle.cs | 25 ----------- .../WorkflowDefinitionPersistenceFeature.cs | 1 + .../WorkflowInstancePersistenceFeature.cs | 2 +- .../WorkflowManagementPersistenceFeature.cs | 28 +++++-------- .../WorkflowRuntimePersistenceFeature.cs | 1 - 31 files changed, 127 insertions(+), 132 deletions(-) rename docker/{init-db.sh => init-db-postgres.sh} (100%) create mode 100755 docker/oracle-setup/setup.sql delete mode 100644 src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/SetupForOracle.cs rename src/modules/{Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs => Elsa.EntityFrameworkCore.Oracle/SetupForAlterations.cs} (88%) create mode 100644 src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForManagement.cs rename src/modules/{Elsa.EntityFrameworkCore/Modules/Runtime/SetupForOracle.cs => Elsa.EntityFrameworkCore.Oracle/SetupForRuntime.cs} (95%) rename src/modules/{Elsa.EntityFrameworkCore.Common/EntityHandlers => Elsa.EntityFrameworkCore.Sqlite}/SetupForSqlite.cs (95%) delete mode 100644 src/modules/Elsa.EntityFrameworkCore/Modules/Management/SetupForOracle.cs diff --git a/Elsa.sln b/Elsa.sln index 619e260be..0091ff928 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -89,9 +89,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54 docker\ElsaServer.Dockerfile = docker\ElsaServer.Dockerfile docker\ElsaServerAndStudio.Dockerfile = docker\ElsaServerAndStudio.Dockerfile docker\ElsaStudio.Dockerfile = docker\ElsaStudio.Dockerfile - docker\init-db.sh = docker\init-db.sh docker\otel-collector-config.yaml = docker\otel-collector-config.yaml docker\docker-compose-kafka.yml = docker\docker-compose-kafka.yml + docker\init-db-postgres.sh = docker\init-db-postgres.sh EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Elasticsearch", "src\modules\Elsa.Elasticsearch\Elsa.Elasticsearch.csproj", "{3246883E-2FA7-4B4A-BDC5-99039A2869BC}" @@ -387,6 +387,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Agents.Persistence.Ent EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Kafka", "src\modules\Elsa.Kafka\Elsa.Kafka.csproj", "{BF934627-F531-44FB-BEC2-ECA801FF31E7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "oracle-setup", "oracle-setup", "{66E2E2CF-967F-4564-89E8-F46FA973C99B}" + ProjectSection(SolutionItems) = preProject + docker\oracle-setup\setup.sql = docker\oracle-setup\setup.sql + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -968,6 +973,7 @@ Global {2B939AC9-03A4-479E-AA0D-CB58F4A7F480} = {50470834-4CD8-479A-8B58-0A1869BA5D37} {2CDF3E1C-267D-4198-B1C7-7E1F548FC120} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {BF934627-F531-44FB-BEC2-ECA801FF31E7} = {DD089B8B-DA73-492A-9010-F772D1C178DA} + {66E2E2CF-967F-4564-89E8-F46FA973C99B} = {986E5482-0482-448C-B9E4-EC67A9474B85} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E} diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 58f37a11b..8d76746a1 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -27,16 +27,15 @@ oracle: image: container-registry.oracle.com/database/free:latest - container_name: oracle + container_name: oracle-db environment: - ORACLE_PDB: ORCLPDB1 ORACLE_PWD: elsa ports: - "1521:1521" - "5500:5500" volumes: - - oracle-data-free:/opt/oracle/oradata - shm_size: '1g' + - ./oracle-data-free1:/opt/oracle/oradata + - ./oracle-setup:/opt/oracle/scripts/setup mongodb: image: mongo:latest @@ -128,7 +127,7 @@ volumes: postgres-data: - oracle-data-free: + oracle-data-free1: mysql_data2: cockroachdb-data: mongodb_data: diff --git a/docker/init-db.sh b/docker/init-db-postgres.sh similarity index 100% rename from docker/init-db.sh rename to docker/init-db-postgres.sh diff --git a/docker/oracle-setup/setup.sql b/docker/oracle-setup/setup.sql new file mode 100755 index 000000000..311441d40 --- /dev/null +++ b/docker/oracle-setup/setup.sql @@ -0,0 +1,3 @@ +alter session set "_ORACLE_SCRIPT"=true; +CREATE USER ELSA IDENTIFIED BY elsa; +GRANT ALL PRIVILEGES TO ELSA; \ No newline at end of file diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index 0e9985ad8..af30c1b66 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -9,6 +9,7 @@ using Elsa.Common.Serialization; using Elsa.Dapper.Extensions; using Elsa.Dapper.Services; using Elsa.DropIns.Extensions; +using Elsa.EntityFrameworkCore; using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.Modules.Alterations; using Elsa.EntityFrameworkCore.Modules.Identity; @@ -197,7 +198,7 @@ services else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) - ef.UseOracle(oracleConnectionString); + ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"}); else ef.UseSqlite(sp => sp.GetSqliteConnectionString()); @@ -235,7 +236,7 @@ services else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString!); else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) - ef.UseOracle(oracleConnectionString); + ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"}); else ef.UseSqlite(sp => sp.GetSqliteConnectionString()); @@ -283,7 +284,7 @@ services else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString); else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) - ef.UseOracle(oracleConnectionString); + ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"}); else ef.UseSqlite(sp => sp.GetSqliteConnectionString()); @@ -420,7 +421,7 @@ services else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) ef.UsePostgreSql(cockroachDbConnectionString); else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) - ef.UseOracle(oracleConnectionString); + ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"}); else ef.UseSqlite(sp => sp.GetSqliteConnectionString()); @@ -623,7 +624,7 @@ services if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite) ef.UseSqlite(sqliteConnectionString); if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString); if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString); - if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) ef.UseOracle(oracleConnectionString); + if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"}); #if !NET9_0 if (sqlDatabaseProvider == SqlDatabaseProvider.MySql) ef.UseMySql(mySqlConnectionString); diff --git a/src/apps/Elsa.Server.Web/appsettings.json b/src/apps/Elsa.Server.Web/appsettings.json index 20591e80b..a1d35303b 100644 --- a/src/apps/Elsa.Server.Web/appsettings.json +++ b/src/apps/Elsa.Server.Web/appsettings.json @@ -13,7 +13,7 @@ "Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;", "MySql": "Server=localhost;Database=elsa;Uid=admin;Pwd=password;", "PostgreSql": "Server=localhost;Username=elsa;Database=elsa;Port=5432;Password=elsa;SSLMode=Prefer;MaxPoolSize=2000;Timeout=60", - "Oracle": "User Id=SYSTEM;Password=elsa;Data Source=localhost:1521/FREE;", + "Oracle": "Data Source=(DESCRIPTION = (ADDRESS_LIST = (FAILOVER =ON) (LOAD_BALANCE = OFF) (ADDRESS = (PROTOCOL =TCP)(HOST=localhost)(PORT=1521))) (CONNECT_DATA = (SID= FREE) ));User Id=ELSA;Password=elsa;", "CockroachDb": "Host=localhost;Port=26257;Database=elsa;SslMode=Disable;Username=root;IncludeErrorDetail=true", "MongoDb": "mongodb://localhost:27017/elsa-workflows", "AzureServiceBus": "", diff --git a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Feature.cs b/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Feature.cs index d5c99065e..67f4d0240 100644 --- a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Feature.cs +++ b/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Feature.cs @@ -34,6 +34,5 @@ public class EFCoreAgentPersistenceFeature(IModule module) : PersistenceFeatureB AddEntityStore(); AddEntityStore(); AddEntityStore(); - Services.AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/SetupForOracle.cs b/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/SetupForOracle.cs deleted file mode 100644 index 1dec01e7d..000000000 --- a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/SetupForOracle.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Elsa.Agents.Persistence.Entities; -using Elsa.EntityFrameworkCore; -using Elsa.EntityFrameworkCore.Extensions; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace Elsa.Agents.Persistence.EntityFrameworkCore; - -/// -/// Represents a class that handles entity model creation for SQLite databases. -/// -public class SetupForOracle : IEntityModelCreatingHandler -{ - /// - public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) - { - if(!dbContext.Database.IsOracle()) - return; - - // In order to use data more than 2000 char we have to use NCLOB. - // In Oracle, we have to explicitly say the column is NCLOB otherwise it would be considered nvarchar(2000). - modelBuilder.Entity().Property("SerializedSettings").HasColumnType("NCLOB"); - modelBuilder.Entity().Property("SerializedAgentConfig").HasColumnType("NCLOB"); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs index 42f681a5d..835574f21 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/CommonPersistenceFeature.cs @@ -13,6 +13,5 @@ public class CommonPersistenceFeature(IModule module) : FeatureBase(module) { Services.AddScoped(); Services.AddScoped(); - Services.AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/DbSchemaAwareMigrationAssembly.cs b/src/modules/Elsa.EntityFrameworkCore.Common/DbSchemaAwareMigrationAssembly.cs index 21ab52188..5e31b710e 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/DbSchemaAwareMigrationAssembly.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/DbSchemaAwareMigrationAssembly.cs @@ -10,17 +10,14 @@ namespace Elsa.EntityFrameworkCore; /// /// Class That enable Schema change for Migration /// -public class DbSchemaAwareMigrationAssembly : MigrationsAssembly +public class DbSchemaAwareMigrationAssembly( + ICurrentDbContext currentContext, + IDbContextOptions options, + IMigrationsIdGenerator idGenerator, + IDiagnosticsLogger logger) + : MigrationsAssembly(currentContext, options, idGenerator, logger) { - private readonly DbContext _context; - - public DbSchemaAwareMigrationAssembly(ICurrentDbContext currentContext, - IDbContextOptions options, IMigrationsIdGenerator idGenerator, - IDiagnosticsLogger logger) - : base(currentContext, options, idGenerator, logger) - { - _context = currentContext.Context; - } + private readonly DbContext _context = currentContext.Context; public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider) { diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj b/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj index 723566266..e3f4635d9 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj +++ b/src/modules/Elsa.EntityFrameworkCore.Common/Elsa.EntityFrameworkCore.Common.csproj @@ -12,7 +12,6 @@ - diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs index 85407dff4..4e14923f2 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs @@ -61,6 +61,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + optionsBuilder.EnableSensitiveDataLogging(); #if NET9_0_OR_GREATER optionsBuilder.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning)); #endif @@ -71,8 +72,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema { if (!string.IsNullOrWhiteSpace(Schema)) { - if (!Database.IsSqlite()) - modelBuilder.HasDefaultSchema(Schema); + modelBuilder.HasDefaultSchema(Schema); } var entityTypeHandlers = ServiceProvider.GetServices().ToList(); diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs index 031f69397..5df4f3a07 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/PersistenceFeatureBase.cs @@ -39,11 +39,7 @@ public abstract class PersistenceFeatureBase : FeatureBase /// /// Gets or sets the callback used to configure the . /// - public Action DbContextOptionsBuilder = (_, options) => options - .UseElsaDbContextOptions(default) - .UseSqlite("Data Source=elsa.sqlite.db;Cache=Shared;", sqlite => sqlite - .MigrationsAssembly("Elsa.EntityFrameworkCore.Sqlite") - .MigrationsHistoryTable(ElsaDbContextBase.MigrationsHistoryTable, ElsaDbContextBase.ElsaSchema)); + public virtual Action DbContextOptionsBuilder { get; set; } = null!; public override void ConfigureHostedServices() { @@ -54,6 +50,9 @@ public abstract class PersistenceFeatureBase : FeatureBase /// public override void Apply() { + if(DbContextOptionsBuilder == null) + throw new InvalidOperationException("The DbContextOptionsBuilder must be configured."); + if (UseContextPooling) Services.AddPooledDbContextFactory(DbContextOptionsBuilder); else diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Alterations/20241212211620_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Alterations/20241212211620_V3_3.cs index 97bd8dd6c..fb7daa451 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Alterations/20241212211620_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Alterations/20241212211620_V3_3.cs @@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Alterations protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "AlterationJobs", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Identity/20241212211936_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Identity/20241212211936_V3_3.cs index baed52c99..f9c5d3188 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Identity/20241212211936_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Identity/20241212211936_V3_3.cs @@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Identity protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "Applications", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Labels/20241212212100_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Labels/20241212212100_V3_3.cs index dbfb65ccd..af7faf037 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Labels/20241212212100_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Labels/20241212212100_V3_3.cs @@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Labels protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "Labels", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Management/20241212211817_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Management/20241212211817_V3_3.cs index 57217614d..e3ba33c57 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Management/20241212211817_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Management/20241212211817_V3_3.cs @@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Management protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "WorkflowDefinitions", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Runtime/20250116193207_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Runtime/20250116193207_V3_3.cs index a026586c5..133e73074 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Runtime/20250116193207_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Runtime/20250116193207_V3_3.cs @@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Runtime protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "ActivityExecutionRecords", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Tenants/20241212212227_V3_3.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Tenants/20241212212227_V3_3.cs index 8ca9f1711..1860609ac 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Tenants/20241212212227_V3_3.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/Migrations/Tenants/20241212212227_V3_3.cs @@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Tenants protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.CreateTable( name: "Tenants", diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/OracleProvidersExtensions.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/OracleProvidersExtensions.cs index 002b87541..191a08eb2 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Oracle/OracleProvidersExtensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/OracleProvidersExtensions.cs @@ -1,5 +1,10 @@ using System.Reflection; +using Elsa.EntityFrameworkCore.Modules.Alterations; +using Elsa.EntityFrameworkCore.Oracle; +using Elsa.Extensions; using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Oracle.EntityFrameworkCore.Infrastructure; // ReSharper disable once CheckNamespace @@ -12,49 +17,53 @@ namespace Elsa.EntityFrameworkCore.Extensions; public static class OracleProvidersExtensions { private static Assembly Assembly => typeof(OracleProvidersExtensions).Assembly; - - public static TFeature UseOracle(this PersistenceFeatureBase feature, - string connectionString, - ElsaDbContextOptions? options = null, - Action? configure = null) + + public static TFeature UseOracle(this PersistenceFeatureBase feature, + string connectionString, + ElsaDbContextOptions? options = null, + Action? configure = null) where TDbContext : ElsaDbContextBase where TFeature : PersistenceFeatureBase { return feature.UseOracle(Assembly, connectionString, options, configure); } - - public static TFeature UseOracle(this PersistenceFeatureBase feature, + + public static TFeature UseOracle(this PersistenceFeatureBase feature, Func connectionStringFunc, ElsaDbContextOptions? options = null, Action? configure = null - ) + ) where TDbContext : ElsaDbContextBase where TFeature : PersistenceFeatureBase { return feature.UseOracle(Assembly, connectionStringFunc, options, configure); } - - public static TFeature UseOracle(this PersistenceFeatureBase feature, - Assembly migrationsAssembly, + + public static TFeature UseOracle(this PersistenceFeatureBase feature, + Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options = null, Action? configure = null - ) + ) where TDbContext : ElsaDbContextBase where TFeature : PersistenceFeatureBase { return feature.UseOracle(migrationsAssembly, _ => connectionString, options, configure); } - - public static TFeature UseOracle(this PersistenceFeatureBase feature, - Assembly migrationsAssembly, + + public static TFeature UseOracle(this PersistenceFeatureBase feature, + Assembly migrationsAssembly, Func connectionStringFunc, ElsaDbContextOptions? options = null, Action? configure = null - ) + ) where TDbContext : ElsaDbContextBase where TFeature : PersistenceFeatureBase { + feature.Services.TryAddScopedImplementation(); + feature.Services.TryAddScopedImplementation(); + feature.Services.TryAddScopedImplementation(); + feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaOracle(migrationsAssembly, connectionStringFunc(sp), options, configure: configure); return (TFeature)feature; } diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForAlterations.cs similarity index 88% rename from src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs rename to src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForAlterations.cs index 8c3b5b2a3..81dc4bff3 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/SetupForOracle.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForAlterations.cs @@ -1,14 +1,13 @@ using Elsa.Alterations.Core.Entities; -using Elsa.EntityFrameworkCore.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; -namespace Elsa.EntityFrameworkCore.Modules.Alterations; +namespace Elsa.EntityFrameworkCore.Oracle; /// /// Represents a class that handles entity model creation for SQLite databases. /// -public class SetupForOracle : IEntityModelCreatingHandler +public class SetupForAlterations : IEntityModelCreatingHandler { /// public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) diff --git a/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForManagement.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForManagement.cs new file mode 100644 index 000000000..c7ba3e7bb --- /dev/null +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForManagement.cs @@ -0,0 +1,39 @@ +using System.Linq.Expressions; +using Elsa.Workflows.Management.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Elsa.EntityFrameworkCore.Oracle; + +/// +/// Represents a class that handles entity model creation for SQLite databases. +/// +public class SetupForManagement : IEntityModelCreatingHandler +{ + private static Expression> VersionToStringConverter => v => v != null ? v.ToString() : null; + private static Expression> StringToVersionConverter => v => v != null ? Version.Parse(v) : null; + + /// + public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) + { + if(!dbContext.Database.IsOracle()) + return; + + // In order to use data more than 2000 char we have to use NCLOB. + // In Oracle, we have to explicitly say the column is NCLOB otherwise it would be considered nvarchar(2000). + modelBuilder.Entity().Property("Data").HasColumnType("NCLOB"); + modelBuilder.Entity().Ignore(x => x.WorkflowState); + modelBuilder.Entity().Ignore(x => x.CustomProperties); + modelBuilder.Entity().Ignore(x => x.Variables); + modelBuilder.Entity().Ignore(x => x.Inputs); + modelBuilder.Entity().Ignore(x => x.Outputs); + modelBuilder.Entity().Ignore(x => x.Outcomes); + modelBuilder.Entity().Ignore(x => x.Options); + modelBuilder.Entity().Property(x => x.ToolVersion).HasConversion(VersionToStringConverter, StringToVersionConverter); + modelBuilder.Entity().Property("StringData").HasColumnType("NCLOB"); + modelBuilder.Entity().Property("Data").HasColumnType("NCLOB"); + modelBuilder.Entity().Property(x => x.Description).HasColumnType("NCLOB"); + modelBuilder.Entity().Property(x => x.MaterializerContext).HasColumnType("NCLOB"); + modelBuilder.Entity().Property(x => x.BinaryData).HasColumnType("BLOB"); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/SetupForOracle.cs b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForRuntime.cs similarity index 95% rename from src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/SetupForOracle.cs rename to src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForRuntime.cs index 9820dfbab..1ccab2951 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/SetupForOracle.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Oracle/SetupForRuntime.cs @@ -1,15 +1,14 @@ -using Elsa.EntityFrameworkCore.Extensions; using Elsa.KeyValues.Entities; using Elsa.Workflows.Runtime.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; -namespace Elsa.EntityFrameworkCore.Modules.Runtime; +namespace Elsa.EntityFrameworkCore.Oracle; /// /// Represents a class that handles entity model creation for SQLite databases. /// -public class SetupForOracle : IEntityModelCreatingHandler +public class SetupForRuntime : IEntityModelCreatingHandler { /// public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/SetupForSqlite.cs similarity index 95% rename from src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs rename to src/modules/Elsa.EntityFrameworkCore.Sqlite/SetupForSqlite.cs index 500c6f176..8d60ac962 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetupForSqlite.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/SetupForSqlite.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -namespace Elsa.EntityFrameworkCore.EntityHandlers; +namespace Elsa.EntityFrameworkCore.Sqlite; /// /// Represents a class that handles entity model creation for SQLite databases. diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/SqliteProvidersExtensions.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/SqliteProvidersExtensions.cs index 635abfac5..561b35428 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/SqliteProvidersExtensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/SqliteProvidersExtensions.cs @@ -1,7 +1,10 @@ using System.Reflection; using Elsa.EntityFrameworkCore.EntityHandlers; +using Elsa.EntityFrameworkCore.Sqlite; +using Elsa.Extensions; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; // ReSharper disable once CheckNamespace namespace Elsa.EntityFrameworkCore.Extensions; @@ -65,7 +68,8 @@ public static class SqliteProvidersExtensions where TDbContext : ElsaDbContextBase where TFeature : PersistenceFeatureBase { - feature.Module.Services.AddScoped(); + + feature.Module.Services.TryAddScopedImplementation(); feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaSqlite(migrationsAssembly, connectionStringFunc(sp), options, configure: configure); return (TFeature)feature; } diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs index f05d8442d..de79b7815 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Alterations/Feature.cs @@ -28,6 +28,5 @@ public class EFCoreAlterationsPersistenceFeature(IModule module) : PersistenceFe base.Apply(); AddEntityStore(); AddEntityStore(); - Services.AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/SetupForOracle.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/SetupForOracle.cs deleted file mode 100644 index da338d428..000000000 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/SetupForOracle.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Elsa.EntityFrameworkCore.Extensions; -using Elsa.Workflows.Management.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace Elsa.EntityFrameworkCore.Modules.Management; - -/// -/// Represents a class that handles entity model creation for SQLite databases. -/// -public class SetupForOracle : IEntityModelCreatingHandler -{ - /// - public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) - { - if(!dbContext.Database.IsOracle()) - return; - - // In order to use data more than 2000 char we have to use NCLOB. - // In Oracle, we have to explicitly say the column is NCLOB otherwise it would be considered nvarchar(2000). - modelBuilder.Entity().Property("Data").HasColumnType("NCLOB"); - modelBuilder.Entity().Property("StringData").HasColumnType("NCLOB"); - modelBuilder.Entity().Property("Data").HasColumnType("NCLOB"); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs index b84f3ef23..3b808a942 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs @@ -10,6 +10,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Management; /// Configures the feature with an Entity Framework Core persistence provider. /// [DependsOn(typeof(WorkflowManagementFeature))] +[DependsOn(typeof(WorkflowDefinitionsFeature))] public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : PersistenceFeatureBase(module) { /// diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstancePersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstancePersistenceFeature.cs index 8858c9757..de019e808 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstancePersistenceFeature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstancePersistenceFeature.cs @@ -10,6 +10,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Management; /// Configures the feature with an Entity Framework Core persistence provider. /// [DependsOn(typeof(WorkflowManagementFeature))] +[DependsOn(typeof(WorkflowInstancesFeature))] public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : PersistenceFeatureBase(module) { /// @@ -23,6 +24,5 @@ public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : Persiste { base.Apply(); AddEntityStore(); - Services.AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowManagementPersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowManagementPersistenceFeature.cs index 5699442c6..09e9e20b2 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowManagementPersistenceFeature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowManagementPersistenceFeature.cs @@ -1,33 +1,27 @@ using Elsa.Features.Attributes; using Elsa.Features.Services; -using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Features; using JetBrains.Annotations; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.EntityFrameworkCore; namespace Elsa.EntityFrameworkCore.Modules.Management; /// /// Configures the and features with an Entity Framework Core persistence provider. /// -[DependsOn(typeof(WorkflowManagementFeature))] -[DependsOn(typeof(WorkflowInstancesFeature))] -[DependsOn(typeof(WorkflowDefinitionsFeature))] +[DependsOn(typeof(EFCoreWorkflowInstancePersistenceFeature))] +[DependsOn(typeof(EFCoreWorkflowDefinitionPersistenceFeature))] [PublicAPI] public class WorkflowManagementPersistenceFeature(IModule module) : PersistenceFeatureBase(module) { - /// - public override void Configure() + public override Action DbContextOptionsBuilder { - Module.Configure(feature => feature.WorkflowInstanceStore = sp => sp.GetRequiredService()); - Module.Configure(feature => feature.WorkflowDefinitionStore = sp => sp.GetRequiredService()); - } - - /// - public override void Apply() - { - base.Apply(); - AddEntityStore(); - AddEntityStore(); + get => base.DbContextOptionsBuilder; + set + { + base.DbContextOptionsBuilder = value; + Module.Configure(x => x.DbContextOptionsBuilder = value); + Module.Configure(x => x.DbContextOptionsBuilder = value); + } } } \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/WorkflowRuntimePersistenceFeature.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/WorkflowRuntimePersistenceFeature.cs index f7b5a00be..a3ab463db 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/WorkflowRuntimePersistenceFeature.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/WorkflowRuntimePersistenceFeature.cs @@ -41,6 +41,5 @@ public class EFCoreWorkflowRuntimePersistenceFeature(IModule module) : Persisten AddEntityStore(); AddEntityStore(); AddStore(); - Services.AddScoped(); } } \ No newline at end of file