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.
This commit is contained in:
Sipke Schoorstra 2025-01-31 19:51:24 +01:00
parent 006e0bbbb4
commit 6c0d1ea66c
31 changed files with 127 additions and 132 deletions

View file

@ -89,9 +89,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54
docker\ElsaServer.Dockerfile = docker\ElsaServer.Dockerfile docker\ElsaServer.Dockerfile = docker\ElsaServer.Dockerfile
docker\ElsaServerAndStudio.Dockerfile = docker\ElsaServerAndStudio.Dockerfile docker\ElsaServerAndStudio.Dockerfile = docker\ElsaServerAndStudio.Dockerfile
docker\ElsaStudio.Dockerfile = docker\ElsaStudio.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\otel-collector-config.yaml = docker\otel-collector-config.yaml
docker\docker-compose-kafka.yml = docker\docker-compose-kafka.yml docker\docker-compose-kafka.yml = docker\docker-compose-kafka.yml
docker\init-db-postgres.sh = docker\init-db-postgres.sh
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Elasticsearch", "src\modules\Elsa.Elasticsearch\Elsa.Elasticsearch.csproj", "{3246883E-2FA7-4B4A-BDC5-99039A2869BC}" 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Kafka", "src\modules\Elsa.Kafka\Elsa.Kafka.csproj", "{BF934627-F531-44FB-BEC2-ECA801FF31E7}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Kafka", "src\modules\Elsa.Kafka\Elsa.Kafka.csproj", "{BF934627-F531-44FB-BEC2-ECA801FF31E7}"
EndProject 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -968,6 +973,7 @@ Global
{2B939AC9-03A4-479E-AA0D-CB58F4A7F480} = {50470834-4CD8-479A-8B58-0A1869BA5D37} {2B939AC9-03A4-479E-AA0D-CB58F4A7F480} = {50470834-4CD8-479A-8B58-0A1869BA5D37}
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {2CDF3E1C-267D-4198-B1C7-7E1F548FC120} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
{BF934627-F531-44FB-BEC2-ECA801FF31E7} = {DD089B8B-DA73-492A-9010-F772D1C178DA} {BF934627-F531-44FB-BEC2-ECA801FF31E7} = {DD089B8B-DA73-492A-9010-F772D1C178DA}
{66E2E2CF-967F-4564-89E8-F46FA973C99B} = {986E5482-0482-448C-B9E4-EC67A9474B85}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E} SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E}

View file

@ -27,16 +27,15 @@
oracle: oracle:
image: container-registry.oracle.com/database/free:latest image: container-registry.oracle.com/database/free:latest
container_name: oracle container_name: oracle-db
environment: environment:
ORACLE_PDB: ORCLPDB1
ORACLE_PWD: elsa ORACLE_PWD: elsa
ports: ports:
- "1521:1521" - "1521:1521"
- "5500:5500" - "5500:5500"
volumes: volumes:
- oracle-data-free:/opt/oracle/oradata - ./oracle-data-free1:/opt/oracle/oradata
shm_size: '1g' - ./oracle-setup:/opt/oracle/scripts/setup
mongodb: mongodb:
image: mongo:latest image: mongo:latest
@ -128,7 +127,7 @@
volumes: volumes:
postgres-data: postgres-data:
oracle-data-free: oracle-data-free1:
mysql_data2: mysql_data2:
cockroachdb-data: cockroachdb-data:
mongodb_data: mongodb_data:

3
docker/oracle-setup/setup.sql Executable file
View file

@ -0,0 +1,3 @@
alter session set "_ORACLE_SCRIPT"=true;
CREATE USER ELSA IDENTIFIED BY elsa;
GRANT ALL PRIVILEGES TO ELSA;

View file

@ -9,6 +9,7 @@ using Elsa.Common.Serialization;
using Elsa.Dapper.Extensions; using Elsa.Dapper.Extensions;
using Elsa.Dapper.Services; using Elsa.Dapper.Services;
using Elsa.DropIns.Extensions; using Elsa.DropIns.Extensions;
using Elsa.EntityFrameworkCore;
using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.Extensions;
using Elsa.EntityFrameworkCore.Modules.Alterations; using Elsa.EntityFrameworkCore.Modules.Alterations;
using Elsa.EntityFrameworkCore.Modules.Identity; using Elsa.EntityFrameworkCore.Modules.Identity;
@ -197,7 +198,7 @@ services
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!); ef.UsePostgreSql(cockroachDbConnectionString!);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString); ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"});
else else
ef.UseSqlite(sp => sp.GetSqliteConnectionString()); ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -235,7 +236,7 @@ services
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!); ef.UsePostgreSql(cockroachDbConnectionString!);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString); ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"});
else else
ef.UseSqlite(sp => sp.GetSqliteConnectionString()); ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -283,7 +284,7 @@ services
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString); ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString); ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"});
else else
ef.UseSqlite(sp => sp.GetSqliteConnectionString()); ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -420,7 +421,7 @@ services
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb) else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString); ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString); ef.UseOracle(oracleConnectionString, new ElsaDbContextOptions{ SchemaName = "ELSA"});
else else
ef.UseSqlite(sp => sp.GetSqliteConnectionString()); ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -623,7 +624,7 @@ services
if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite) ef.UseSqlite(sqliteConnectionString); if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite) ef.UseSqlite(sqliteConnectionString);
if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString); if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer) ef.UseSqlServer(sqlServerConnectionString);
if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString); 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 !NET9_0
if (sqlDatabaseProvider == SqlDatabaseProvider.MySql) if (sqlDatabaseProvider == SqlDatabaseProvider.MySql)
ef.UseMySql(mySqlConnectionString); ef.UseMySql(mySqlConnectionString);

View file

@ -13,7 +13,7 @@
"Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;", "Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;",
"MySql": "Server=localhost;Database=elsa;Uid=admin;Pwd=password;", "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", "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", "CockroachDb": "Host=localhost;Port=26257;Database=elsa;SslMode=Disable;Username=root;IncludeErrorDetail=true",
"MongoDb": "mongodb://localhost:27017/elsa-workflows", "MongoDb": "mongodb://localhost:27017/elsa-workflows",
"AzureServiceBus": "", "AzureServiceBus": "",

View file

@ -34,6 +34,5 @@ public class EFCoreAgentPersistenceFeature(IModule module) : PersistenceFeatureB
AddEntityStore<ApiKeyDefinition, EFCoreApiKeyStore>(); AddEntityStore<ApiKeyDefinition, EFCoreApiKeyStore>();
AddEntityStore<ServiceDefinition, EFCoreServiceStore>(); AddEntityStore<ServiceDefinition, EFCoreServiceStore>();
AddEntityStore<AgentDefinition, EFCoreAgentStore>(); AddEntityStore<AgentDefinition, EFCoreAgentStore>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForOracle>();
} }
} }

View file

@ -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;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.
/// </summary>
public class SetupForOracle : IEntityModelCreatingHandler
{
/// <inheritdoc />
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<ServiceDefinition>().Property<string>("SerializedSettings").HasColumnType("NCLOB");
modelBuilder.Entity<AgentDefinition>().Property<string>("SerializedAgentConfig").HasColumnType("NCLOB");
}
}

View file

@ -13,6 +13,5 @@ public class CommonPersistenceFeature(IModule module) : FeatureBase(module)
{ {
Services.AddScoped<IEntitySavingHandler, ApplyTenantId>(); Services.AddScoped<IEntitySavingHandler, ApplyTenantId>();
Services.AddScoped<IEntityModelCreatingHandler, SetTenantIdFilter>(); Services.AddScoped<IEntityModelCreatingHandler, SetTenantIdFilter>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForSqlite>();
} }
} }

View file

@ -10,17 +10,14 @@ namespace Elsa.EntityFrameworkCore;
/// <summary> /// <summary>
/// Class That enable Schema change for Migration /// Class That enable Schema change for Migration
/// </summary> /// </summary>
public class DbSchemaAwareMigrationAssembly : MigrationsAssembly public class DbSchemaAwareMigrationAssembly(
ICurrentDbContext currentContext,
IDbContextOptions options,
IMigrationsIdGenerator idGenerator,
IDiagnosticsLogger<DbLoggerCategory.Migrations> logger)
: MigrationsAssembly(currentContext, options, idGenerator, logger)
{ {
private readonly DbContext _context; private readonly DbContext _context = currentContext.Context;
public DbSchemaAwareMigrationAssembly(ICurrentDbContext currentContext,
IDbContextOptions options, IMigrationsIdGenerator idGenerator,
IDiagnosticsLogger<DbLoggerCategory.Migrations> logger)
: base(currentContext, options, idGenerator, logger)
{
_context = currentContext.Context;
}
public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider) public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
{ {

View file

@ -12,7 +12,6 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" /> <PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="Open.Linq.AsyncExtensions" /> <PackageReference Include="Open.Linq.AsyncExtensions" />
<PackageReference Include="System.CommandLine" /> <PackageReference Include="System.CommandLine" />

View file

@ -61,6 +61,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
optionsBuilder.EnableSensitiveDataLogging();
#if NET9_0_OR_GREATER #if NET9_0_OR_GREATER
optionsBuilder.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning)); optionsBuilder.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning));
#endif #endif
@ -71,8 +72,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema
{ {
if (!string.IsNullOrWhiteSpace(Schema)) if (!string.IsNullOrWhiteSpace(Schema))
{ {
if (!Database.IsSqlite()) modelBuilder.HasDefaultSchema(Schema);
modelBuilder.HasDefaultSchema(Schema);
} }
var entityTypeHandlers = ServiceProvider.GetServices<IEntityModelCreatingHandler>().ToList(); var entityTypeHandlers = ServiceProvider.GetServices<IEntityModelCreatingHandler>().ToList();

View file

@ -39,11 +39,7 @@ public abstract class PersistenceFeatureBase<TFeature, TDbContext> : FeatureBase
/// <summary> /// <summary>
/// Gets or sets the callback used to configure the <see cref="DbContextOptionsBuilder"/>. /// Gets or sets the callback used to configure the <see cref="DbContextOptionsBuilder"/>.
/// </summary> /// </summary>
public Action<IServiceProvider, DbContextOptionsBuilder> DbContextOptionsBuilder = (_, options) => options public virtual Action<IServiceProvider, DbContextOptionsBuilder> DbContextOptionsBuilder { get; set; } = null!;
.UseElsaDbContextOptions(default)
.UseSqlite("Data Source=elsa.sqlite.db;Cache=Shared;", sqlite => sqlite
.MigrationsAssembly("Elsa.EntityFrameworkCore.Sqlite")
.MigrationsHistoryTable(ElsaDbContextBase.MigrationsHistoryTable, ElsaDbContextBase.ElsaSchema));
public override void ConfigureHostedServices() public override void ConfigureHostedServices()
{ {
@ -54,6 +50,9 @@ public abstract class PersistenceFeatureBase<TFeature, TDbContext> : FeatureBase
/// <inheritdoc /> /// <inheritdoc />
public override void Apply() public override void Apply()
{ {
if(DbContextOptionsBuilder == null)
throw new InvalidOperationException("The DbContextOptionsBuilder must be configured.");
if (UseContextPooling) if (UseContextPooling)
Services.AddPooledDbContextFactory<TDbContext>(DbContextOptionsBuilder); Services.AddPooledDbContextFactory<TDbContext>(DbContextOptionsBuilder);
else else

View file

@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Alterations
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AlterationJobs", name: "AlterationJobs",

View file

@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Identity
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Applications", name: "Applications",

View file

@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Labels
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Labels", name: "Labels",

View file

@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Management
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "WorkflowDefinitions", name: "WorkflowDefinitions",

View file

@ -20,7 +20,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Runtime
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "ActivityExecutionRecords", name: "ActivityExecutionRecords",

View file

@ -19,7 +19,7 @@ namespace Elsa.EntityFrameworkCore.Oracle.Migrations.Tenants
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema( migrationBuilder.EnsureSchema(
name: "Elsa"); name: _schema.Schema);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Tenants", name: "Tenants",

View file

@ -1,5 +1,10 @@
using System.Reflection; using System.Reflection;
using Elsa.EntityFrameworkCore.Modules.Alterations;
using Elsa.EntityFrameworkCore.Oracle;
using Elsa.Extensions;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Oracle.EntityFrameworkCore.Infrastructure; using Oracle.EntityFrameworkCore.Infrastructure;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
@ -55,6 +60,10 @@ public static class OracleProvidersExtensions
where TDbContext : ElsaDbContextBase where TDbContext : ElsaDbContextBase
where TFeature : PersistenceFeatureBase<TFeature, TDbContext> where TFeature : PersistenceFeatureBase<TFeature, TDbContext>
{ {
feature.Services.TryAddScopedImplementation<IEntityModelCreatingHandler, SetupForAlterations>();
feature.Services.TryAddScopedImplementation<IEntityModelCreatingHandler, SetupForManagement>();
feature.Services.TryAddScopedImplementation<IEntityModelCreatingHandler, SetupForRuntime>();
feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaOracle(migrationsAssembly, connectionStringFunc(sp), options, configure: configure); feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaOracle(migrationsAssembly, connectionStringFunc(sp), options, configure: configure);
return (TFeature)feature; return (TFeature)feature;
} }

View file

@ -1,14 +1,13 @@
using Elsa.Alterations.Core.Entities; using Elsa.Alterations.Core.Entities;
using Elsa.EntityFrameworkCore.Extensions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
namespace Elsa.EntityFrameworkCore.Modules.Alterations; namespace Elsa.EntityFrameworkCore.Oracle;
/// <summary> /// <summary>
/// Represents a class that handles entity model creation for SQLite databases. /// Represents a class that handles entity model creation for SQLite databases.
/// </summary> /// </summary>
public class SetupForOracle : IEntityModelCreatingHandler public class SetupForAlterations : IEntityModelCreatingHandler
{ {
/// <inheritdoc /> /// <inheritdoc />
public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType)

View file

@ -0,0 +1,39 @@
using System.Linq.Expressions;
using Elsa.Workflows.Management.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace Elsa.EntityFrameworkCore.Oracle;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.
/// </summary>
public class SetupForManagement : IEntityModelCreatingHandler
{
private static Expression<Func<Version?, string?>> VersionToStringConverter => v => v != null ? v.ToString() : null;
private static Expression<Func<string?, Version?>> StringToVersionConverter => v => v != null ? Version.Parse(v) : null;
/// <inheritdoc />
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<WorkflowInstance>().Property<string>("Data").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInstance>().Ignore(x => x.WorkflowState);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.CustomProperties);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.Variables);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.Inputs);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.Outputs);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.Outcomes);
modelBuilder.Entity<WorkflowDefinition>().Ignore(x => x.Options);
modelBuilder.Entity<WorkflowDefinition>().Property(x => x.ToolVersion).HasConversion(VersionToStringConverter, StringToVersionConverter);
modelBuilder.Entity<WorkflowDefinition>().Property<string>("StringData").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property<string>("Data").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property(x => x.Description).HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property(x => x.MaterializerContext).HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property(x => x.BinaryData).HasColumnType("BLOB");
}
}

View file

@ -1,15 +1,14 @@
using Elsa.EntityFrameworkCore.Extensions;
using Elsa.KeyValues.Entities; using Elsa.KeyValues.Entities;
using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Entities;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
namespace Elsa.EntityFrameworkCore.Modules.Runtime; namespace Elsa.EntityFrameworkCore.Oracle;
/// <summary> /// <summary>
/// Represents a class that handles entity model creation for SQLite databases. /// Represents a class that handles entity model creation for SQLite databases.
/// </summary> /// </summary>
public class SetupForOracle : IEntityModelCreatingHandler public class SetupForRuntime : IEntityModelCreatingHandler
{ {
/// <inheritdoc /> /// <inheritdoc />
public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType)

View file

@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Elsa.EntityFrameworkCore.EntityHandlers; namespace Elsa.EntityFrameworkCore.Sqlite;
/// <summary> /// <summary>
/// Represents a class that handles entity model creation for SQLite databases. /// Represents a class that handles entity model creation for SQLite databases.

View file

@ -1,7 +1,10 @@
using System.Reflection; using System.Reflection;
using Elsa.EntityFrameworkCore.EntityHandlers; using Elsa.EntityFrameworkCore.EntityHandlers;
using Elsa.EntityFrameworkCore.Sqlite;
using Elsa.Extensions;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace Elsa.EntityFrameworkCore.Extensions; namespace Elsa.EntityFrameworkCore.Extensions;
@ -65,7 +68,8 @@ public static class SqliteProvidersExtensions
where TDbContext : ElsaDbContextBase where TDbContext : ElsaDbContextBase
where TFeature : PersistenceFeatureBase<TFeature, TDbContext> where TFeature : PersistenceFeatureBase<TFeature, TDbContext>
{ {
feature.Module.Services.AddScoped<IEntityModelCreatingHandler, SetupForSqlite>();
feature.Module.Services.TryAddScopedImplementation<IEntityModelCreatingHandler, SetupForSqlite>();
feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaSqlite(migrationsAssembly, connectionStringFunc(sp), options, configure: configure); feature.DbContextOptionsBuilder = (sp, db) => db.UseElsaSqlite(migrationsAssembly, connectionStringFunc(sp), options, configure: configure);
return (TFeature)feature; return (TFeature)feature;
} }

View file

@ -28,6 +28,5 @@ public class EFCoreAlterationsPersistenceFeature(IModule module) : PersistenceFe
base.Apply(); base.Apply();
AddEntityStore<AlterationPlan, EFCoreAlterationPlanStore>(); AddEntityStore<AlterationPlan, EFCoreAlterationPlanStore>();
AddEntityStore<AlterationJob, EFCoreAlterationJobStore>(); AddEntityStore<AlterationJob, EFCoreAlterationJobStore>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForOracle>();
} }
} }

View file

@ -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;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.
/// </summary>
public class SetupForOracle : IEntityModelCreatingHandler
{
/// <inheritdoc />
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<WorkflowInstance>().Property<string>("Data").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property<string>("StringData").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property<string>("Data").HasColumnType("NCLOB");
}
}

View file

@ -10,6 +10,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Management;
/// Configures the <see cref="WorkflowDefinitionsFeature"/> feature with an Entity Framework Core persistence provider. /// Configures the <see cref="WorkflowDefinitionsFeature"/> feature with an Entity Framework Core persistence provider.
/// </summary> /// </summary>
[DependsOn(typeof(WorkflowManagementFeature))] [DependsOn(typeof(WorkflowManagementFeature))]
[DependsOn(typeof(WorkflowDefinitionsFeature))]
public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowDefinitionPersistenceFeature, ManagementElsaDbContext>(module) public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowDefinitionPersistenceFeature, ManagementElsaDbContext>(module)
{ {
/// <inheritdoc /> /// <inheritdoc />

View file

@ -10,6 +10,7 @@ namespace Elsa.EntityFrameworkCore.Modules.Management;
/// Configures the <see cref="WorkflowInstancesFeature"/> feature with an Entity Framework Core persistence provider. /// Configures the <see cref="WorkflowInstancesFeature"/> feature with an Entity Framework Core persistence provider.
/// </summary> /// </summary>
[DependsOn(typeof(WorkflowManagementFeature))] [DependsOn(typeof(WorkflowManagementFeature))]
[DependsOn(typeof(WorkflowInstancesFeature))]
public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowInstancePersistenceFeature, ManagementElsaDbContext>(module) public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowInstancePersistenceFeature, ManagementElsaDbContext>(module)
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -23,6 +24,5 @@ public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : Persiste
{ {
base.Apply(); base.Apply();
AddEntityStore<WorkflowInstance, EFCoreWorkflowInstanceStore>(); AddEntityStore<WorkflowInstance, EFCoreWorkflowInstanceStore>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForOracle>();
} }
} }

View file

@ -1,33 +1,27 @@
using Elsa.Features.Attributes; using Elsa.Features.Attributes;
using Elsa.Features.Services; using Elsa.Features.Services;
using Elsa.Workflows.Management.Entities;
using Elsa.Workflows.Management.Features; using Elsa.Workflows.Management.Features;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore;
namespace Elsa.EntityFrameworkCore.Modules.Management; namespace Elsa.EntityFrameworkCore.Modules.Management;
/// <summary> /// <summary>
/// Configures the <see cref="WorkflowInstancesFeature"/> and <see cref="WorkflowDefinitionsFeature"/> features with an Entity Framework Core persistence provider. /// Configures the <see cref="WorkflowInstancesFeature"/> and <see cref="WorkflowDefinitionsFeature"/> features with an Entity Framework Core persistence provider.
/// </summary> /// </summary>
[DependsOn(typeof(WorkflowManagementFeature))] [DependsOn(typeof(EFCoreWorkflowInstancePersistenceFeature))]
[DependsOn(typeof(WorkflowInstancesFeature))] [DependsOn(typeof(EFCoreWorkflowDefinitionPersistenceFeature))]
[DependsOn(typeof(WorkflowDefinitionsFeature))]
[PublicAPI] [PublicAPI]
public class WorkflowManagementPersistenceFeature(IModule module) : PersistenceFeatureBase<WorkflowManagementPersistenceFeature, ManagementElsaDbContext>(module) public class WorkflowManagementPersistenceFeature(IModule module) : PersistenceFeatureBase<WorkflowManagementPersistenceFeature, ManagementElsaDbContext>(module)
{ {
/// <inheritdoc /> public override Action<IServiceProvider, DbContextOptionsBuilder> DbContextOptionsBuilder
public override void Configure()
{ {
Module.Configure<WorkflowInstancesFeature>(feature => feature.WorkflowInstanceStore = sp => sp.GetRequiredService<EFCoreWorkflowInstanceStore>()); get => base.DbContextOptionsBuilder;
Module.Configure<WorkflowDefinitionsFeature>(feature => feature.WorkflowDefinitionStore = sp => sp.GetRequiredService<EFCoreWorkflowDefinitionStore>()); set
} {
base.DbContextOptionsBuilder = value;
/// <inheritdoc /> Module.Configure<EFCoreWorkflowDefinitionPersistenceFeature>(x => x.DbContextOptionsBuilder = value);
public override void Apply() Module.Configure<EFCoreWorkflowInstancePersistenceFeature>(x => x.DbContextOptionsBuilder = value);
{ }
base.Apply();
AddEntityStore<WorkflowInstance, EFCoreWorkflowInstanceStore>();
AddEntityStore<WorkflowDefinition, EFCoreWorkflowDefinitionStore>();
} }
} }

View file

@ -41,6 +41,5 @@ public class EFCoreWorkflowRuntimePersistenceFeature(IModule module) : Persisten
AddEntityStore<WorkflowExecutionLogRecord, EFCoreWorkflowExecutionLogStore>(); AddEntityStore<WorkflowExecutionLogRecord, EFCoreWorkflowExecutionLogStore>();
AddEntityStore<ActivityExecutionRecord, EFCoreActivityExecutionStore>(); AddEntityStore<ActivityExecutionRecord, EFCoreActivityExecutionStore>();
AddStore<SerializedKeyValuePair, EFCoreKeyValueStore>(); AddStore<SerializedKeyValuePair, EFCoreKeyValueStore>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForOracle>();
} }
} }