Add Oracle database support to the project

This commit introduces Oracle database integration by adding necessary configurations, entity mappings, and Docker Compose setup. Oracle-specific mappings ensure compatibility with NCLOB for large data handling. The changes also include updates to appsettings, enum for SqlDatabaseProvider, and project references to support Oracle.
This commit is contained in:
Sipke Schoorstra 2025-01-31 00:31:09 +01:00
parent 2bac9468d4
commit 26e2b1fb56
10 changed files with 69 additions and 25 deletions

View file

@ -24,6 +24,19 @@
- "3306:3306"
volumes:
- mysql_data2:/var/lib/mysql
oracle:
image: container-registry.oracle.com/database/free:latest
container_name: oracle
environment:
ORACLE_PDB: ORCLPDB1
ORACLE_PWD: elsa
ports:
- "1521:1521"
- "5500:5500"
volumes:
- oracle-data-free:/opt/oracle/oradata
shm_size: '1g'
mongodb:
image: mongo:latest
@ -84,7 +97,6 @@
- ASPNETCORE_URLS=http://+:80
- Logging__LogLevel__Default=Information
elsa-server:
build:
context: ../.
@ -116,6 +128,7 @@
volumes:
postgres-data:
oracle-data-free:
mysql_data2:
cockroachdb-data:
mongodb_data:

View file

@ -9,6 +9,7 @@
<ProjectReference Include="..\..\modules\Elsa.Caching.Distributed.MassTransit\Elsa.Caching.Distributed.MassTransit.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Caching.Distributed.ProtoActor\Elsa.Caching.Distributed.ProtoActor.csproj" />
<ProjectReference Include="..\..\modules\Elsa.EntityFrameworkCore.MySql\Elsa.EntityFrameworkCore.MySql.csproj" Condition=" '$(TargetFramework)' != 'net9.0' " />
<ProjectReference Include="..\..\modules\Elsa.EntityFrameworkCore.Oracle\Elsa.EntityFrameworkCore.Oracle.csproj" />
<ProjectReference Include="..\..\modules\Elsa.EntityFrameworkCore.PostgreSql\Elsa.EntityFrameworkCore.PostgreSql.csproj"/>
<ProjectReference Include="..\..\modules\Elsa.Kafka\Elsa.Kafka.csproj" />
<ProjectReference Include="..\..\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj"/>

View file

@ -6,5 +6,6 @@ public enum SqlDatabaseProvider
Sqlite,
MySql,
PostgreSql,
Oracle,
CockroachDb
}

View file

@ -99,6 +99,7 @@ var identityTokenSection = identitySection.GetSection("Tokens");
var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!;
var sqlServerConnectionString = configuration.GetConnectionString("SqlServer")!;
var postgresConnectionString = configuration.GetConnectionString("PostgreSql")!;
var oracleConnectionString = configuration.GetConnectionString("Oracle")!;
var mySqlConnectionString = configuration.GetConnectionString("MySql")!;
var cockroachDbConnectionString = configuration.GetConnectionString("CockroachDb")!;
var mongoDbConnectionString = configuration.GetConnectionString("MongoDb")!;
@ -195,6 +196,8 @@ services
#endif
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString);
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -231,6 +234,8 @@ services
#endif
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString);
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -276,7 +281,9 @@ services
ef.UseMySql(mySqlConnectionString);
#endif
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!);
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString);
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -411,7 +418,9 @@ services
ef.UseMySql(mySqlConnectionString);
#endif
else if (sqlDatabaseProvider == SqlDatabaseProvider.CockroachDb)
ef.UsePostgreSql(cockroachDbConnectionString!);
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString);
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -614,6 +623,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 !NET9_0
if (sqlDatabaseProvider == SqlDatabaseProvider.MySql)
ef.UseMySql(mySqlConnectionString);

View file

@ -13,6 +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=oracle:1521/ORCLPDB1",
"CockroachDb": "Host=localhost;Port=26257;Database=elsa;SslMode=Disable;Username=root;IncludeErrorDetail=true",
"MongoDb": "mongodb://localhost:27017/elsa-workflows",
"AzureServiceBus": "",

View file

@ -19,7 +19,7 @@ public class SetupForOracle : IEntityModelCreatingHandler
// 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("SerializedSettings").HasColumnType("NCLOB");
modelBuilder.Entity<AgentDefinition>().Property("SerializedAgentConfig").HasColumnType("NCLOB");
modelBuilder.Entity<ServiceDefinition>().Property<string>("SerializedSettings").HasColumnType("NCLOB");
modelBuilder.Entity<AgentDefinition>().Property<string>("SerializedAgentConfig").HasColumnType("NCLOB");
}
}

View file

@ -69,7 +69,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema
var entityTypeHandlers = ServiceProvider.GetServices<IEntityModelCreatingHandler>().ToList();
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
foreach (var entityType in modelBuilder.Model.GetEntityTypes().ToList())
{
foreach (var handler in entityTypeHandlers)
{

View file

@ -18,8 +18,11 @@ public class SetupForOracle : IEntityModelCreatingHandler
// 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<AlterationPlan>().Property("SerializedAlterations").HasColumnType("NCLOB");
modelBuilder.Entity<AlterationPlan>().Property("SerializedWorkflowInstanceIds").HasColumnType("NCLOB");
modelBuilder.Entity<AlterationJob>().Property("SerializedLog").HasColumnType("NCLOB");
modelBuilder.Entity<AlterationPlan>().Ignore(x => x.Alterations);
modelBuilder.Entity<AlterationPlan>().Ignore(x => x.WorkflowInstanceFilter);
modelBuilder.Entity<AlterationPlan>().Property<string>("SerializedAlterations").HasColumnType("NCLOB");
modelBuilder.Entity<AlterationPlan>().Property<string>("SerializedWorkflowInstanceFilter").HasColumnType("NCLOB");
modelBuilder.Entity<AlterationJob>().Ignore(x => x.Log);
modelBuilder.Entity<AlterationJob>().Property<string>("SerializedLog").HasColumnType("NCLOB");
}
}

View file

@ -18,8 +18,8 @@ public class SetupForOracle : IEntityModelCreatingHandler
// 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("Data").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property("StringData").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowDefinition>().Property("Data").HasColumnType("NCLOB");
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

@ -19,22 +19,37 @@ public class SetupForOracle : IEntityModelCreatingHandler
// 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<StoredTrigger>().Property("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<StoredTrigger>().Property<string>("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowExecutionLogRecord>().Property("SerializedActivityState").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowExecutionLogRecord>().Property("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowExecutionLogRecord>().Ignore(x => x.ActivityState);
modelBuilder.Entity<WorkflowExecutionLogRecord>().Ignore(x => x.Payload);
modelBuilder.Entity<WorkflowExecutionLogRecord>().Property<string>("SerializedActivityState").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowExecutionLogRecord>().Property<string>("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property("SerializedActivityState").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property("SerializedException").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property("SerializedOutputs").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Ignore(x => x.ActivityState);
modelBuilder.Entity<ActivityExecutionRecord>().Ignore(x => x.Exception);
modelBuilder.Entity<ActivityExecutionRecord>().Ignore(x => x.Payload);
modelBuilder.Entity<ActivityExecutionRecord>().Ignore(x => x.Outputs);
modelBuilder.Entity<ActivityExecutionRecord>().Ignore(x => x.Properties);
modelBuilder.Entity<ActivityExecutionRecord>().Property<string>("SerializedActivityState").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property<string>("SerializedException").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property<string>("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property<string>("SerializedOutputs").HasColumnType("NCLOB");
modelBuilder.Entity<ActivityExecutionRecord>().Property<string>("SerializedProperties").HasColumnType("NCLOB");
modelBuilder.Entity<StoredBookmark>().Property("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<StoredBookmark>().Property("SerializedMetadata").HasColumnType("NCLOB");
modelBuilder.Entity<StoredBookmark>().Ignore(x => x.Payload);
modelBuilder.Entity<StoredBookmark>().Ignore(x => x.Metadata);
modelBuilder.Entity<StoredBookmark>().Property<string>("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<StoredBookmark>().Property<string>("SerializedMetadata").HasColumnType("NCLOB");
modelBuilder.Entity<StoredTrigger>().Ignore(x => x.Payload);
modelBuilder.Entity<StoredTrigger>().Property<string>("SerializedPayload").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInboxMessage>().Property("SerializedInput").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInboxMessage>().Property("SerializedBookmarkPayload").HasColumnType("NCLOB");
modelBuilder.Entity<SerializedKeyValuePair>().Property("SerializedValue").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInboxMessage>().Ignore(x => x.Input);
modelBuilder.Entity<WorkflowInboxMessage>().Ignore(x => x.BookmarkPayload);
modelBuilder.Entity<WorkflowInboxMessage>().Property<string>("SerializedInput").HasColumnType("NCLOB");
modelBuilder.Entity<WorkflowInboxMessage>().Property<string>("SerializedBookmarkPayload").HasColumnType("NCLOB");
modelBuilder.Entity<SerializedKeyValuePair>().Property<string>("SerializedValue").HasColumnType("NCLOB");
}
}