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\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}

View file

@ -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:

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.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);

View file

@ -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": "",

View file

@ -34,6 +34,5 @@ public class EFCoreAgentPersistenceFeature(IModule module) : PersistenceFeatureB
AddEntityStore<ApiKeyDefinition, EFCoreApiKeyStore>();
AddEntityStore<ServiceDefinition, EFCoreServiceStore>();
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<IEntityModelCreatingHandler, SetTenantIdFilter>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForSqlite>();
}
}

View file

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

View file

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

View file

@ -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<IEntityModelCreatingHandler>().ToList();

View file

@ -39,11 +39,7 @@ public abstract class PersistenceFeatureBase<TFeature, TDbContext> : FeatureBase
/// <summary>
/// Gets or sets the callback used to configure the <see cref="DbContextOptionsBuilder"/>.
/// </summary>
public Action<IServiceProvider, DbContextOptionsBuilder> 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<IServiceProvider, DbContextOptionsBuilder> DbContextOptionsBuilder { get; set; } = null!;
public override void ConfigureHostedServices()
{
@ -54,6 +50,9 @@ public abstract class PersistenceFeatureBase<TFeature, TDbContext> : FeatureBase
/// <inheritdoc />
public override void Apply()
{
if(DbContextOptionsBuilder == null)
throw new InvalidOperationException("The DbContextOptionsBuilder must be configured.");
if (UseContextPooling)
Services.AddPooledDbContextFactory<TDbContext>(DbContextOptionsBuilder);
else

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
string connectionString,
ElsaDbContextOptions? options = null,
Action<OracleDbContextOptionsBuilder>? configure = null)
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
string connectionString,
ElsaDbContextOptions? options = null,
Action<OracleDbContextOptionsBuilder>? configure = null)
where TDbContext : ElsaDbContextBase
where TFeature : PersistenceFeatureBase<TFeature, TDbContext>
{
return feature.UseOracle(Assembly, connectionString, options, configure);
}
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
Func<IServiceProvider, string> connectionStringFunc,
ElsaDbContextOptions? options = null,
Action<OracleDbContextOptionsBuilder>? configure = null
)
)
where TDbContext : ElsaDbContextBase
where TFeature : PersistenceFeatureBase<TFeature, TDbContext>
{
return feature.UseOracle(Assembly, connectionStringFunc, options, configure);
}
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
Assembly migrationsAssembly,
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
Assembly migrationsAssembly,
string connectionString,
ElsaDbContextOptions? options = null,
Action<OracleDbContextOptionsBuilder>? configure = null
)
)
where TDbContext : ElsaDbContextBase
where TFeature : PersistenceFeatureBase<TFeature, TDbContext>
{
return feature.UseOracle(migrationsAssembly, _ => connectionString, options, configure);
}
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
Assembly migrationsAssembly,
public static TFeature UseOracle<TFeature, TDbContext>(this PersistenceFeatureBase<TFeature, TDbContext> feature,
Assembly migrationsAssembly,
Func<IServiceProvider, string> connectionStringFunc,
ElsaDbContextOptions? options = null,
Action<OracleDbContextOptionsBuilder>? configure = null
)
)
where TDbContext : ElsaDbContextBase
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);
return (TFeature)feature;
}

View file

@ -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;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.
/// </summary>
public class SetupForOracle : IEntityModelCreatingHandler
public class SetupForAlterations : IEntityModelCreatingHandler
{
/// <inheritdoc />
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.Workflows.Runtime.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace Elsa.EntityFrameworkCore.Modules.Runtime;
namespace Elsa.EntityFrameworkCore.Oracle;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.
/// </summary>
public class SetupForOracle : IEntityModelCreatingHandler
public class SetupForRuntime : IEntityModelCreatingHandler
{
/// <inheritdoc />
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.Storage.ValueConversion;
namespace Elsa.EntityFrameworkCore.EntityHandlers;
namespace Elsa.EntityFrameworkCore.Sqlite;
/// <summary>
/// Represents a class that handles entity model creation for SQLite databases.

View file

@ -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<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);
return (TFeature)feature;
}

View file

@ -28,6 +28,5 @@ public class EFCoreAlterationsPersistenceFeature(IModule module) : PersistenceFe
base.Apply();
AddEntityStore<AlterationPlan, EFCoreAlterationPlanStore>();
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.
/// </summary>
[DependsOn(typeof(WorkflowManagementFeature))]
[DependsOn(typeof(WorkflowDefinitionsFeature))]
public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowDefinitionPersistenceFeature, ManagementElsaDbContext>(module)
{
/// <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.
/// </summary>
[DependsOn(typeof(WorkflowManagementFeature))]
[DependsOn(typeof(WorkflowInstancesFeature))]
public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : PersistenceFeatureBase<EFCoreWorkflowInstancePersistenceFeature, ManagementElsaDbContext>(module)
{
/// <inheritdoc />
@ -23,6 +24,5 @@ public class EFCoreWorkflowInstancePersistenceFeature(IModule module) : Persiste
{
base.Apply();
AddEntityStore<WorkflowInstance, EFCoreWorkflowInstanceStore>();
Services.AddScoped<IEntityModelCreatingHandler, SetupForOracle>();
}
}

View file

@ -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;
/// <summary>
/// Configures the <see cref="WorkflowInstancesFeature"/> and <see cref="WorkflowDefinitionsFeature"/> features with an Entity Framework Core persistence provider.
/// </summary>
[DependsOn(typeof(WorkflowManagementFeature))]
[DependsOn(typeof(WorkflowInstancesFeature))]
[DependsOn(typeof(WorkflowDefinitionsFeature))]
[DependsOn(typeof(EFCoreWorkflowInstancePersistenceFeature))]
[DependsOn(typeof(EFCoreWorkflowDefinitionPersistenceFeature))]
[PublicAPI]
public class WorkflowManagementPersistenceFeature(IModule module) : PersistenceFeatureBase<WorkflowManagementPersistenceFeature, ManagementElsaDbContext>(module)
{
/// <inheritdoc />
public override void Configure()
public override Action<IServiceProvider, DbContextOptionsBuilder> DbContextOptionsBuilder
{
Module.Configure<WorkflowInstancesFeature>(feature => feature.WorkflowInstanceStore = sp => sp.GetRequiredService<EFCoreWorkflowInstanceStore>());
Module.Configure<WorkflowDefinitionsFeature>(feature => feature.WorkflowDefinitionStore = sp => sp.GetRequiredService<EFCoreWorkflowDefinitionStore>());
}
/// <inheritdoc />
public override void Apply()
{
base.Apply();
AddEntityStore<WorkflowInstance, EFCoreWorkflowInstanceStore>();
AddEntityStore<WorkflowDefinition, EFCoreWorkflowDefinitionStore>();
get => base.DbContextOptionsBuilder;
set
{
base.DbContextOptionsBuilder = value;
Module.Configure<EFCoreWorkflowDefinitionPersistenceFeature>(x => x.DbContextOptionsBuilder = value);
Module.Configure<EFCoreWorkflowInstancePersistenceFeature>(x => x.DbContextOptionsBuilder = value);
}
}
}

View file

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