From 452b15fce725b5205bf65ca9bb82c31db9a9e2e7 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Fri, 10 Mar 2023 16:30:57 +0100 Subject: [PATCH 1/3] oracle persistance provides + unit tests --- WorkflowCore.sln | 18 +- .../MigrationContextFactory.cs | 15 + ...20230310125506_InitialDatabase.Designer.cs | 377 ++++++++++++++++++ .../20230310125506_InitialDatabase.cs | 260 ++++++++++++ .../Migrations/OracleContextModelSnapshot.cs | 375 +++++++++++++++++ .../OracleContext.cs | 74 ++++ .../OracleContextFactory.cs | 29 ++ .../WorkflowCore.Persistence.Oracle/README.md | 19 + .../ServiceCollectionExtensions.cs | 24 ++ .../WorkflowCore.Persistence.Oracle.csproj | 43 ++ .../Scenarios/ActivityScenario.cs | 2 +- .../OraclePersistenceProviderFixture.cs | 25 ++ test/WorkflowCore.Tests.Oracle/OracleSetup.cs | 26 ++ .../Properties/AssemblyInfo.cs | 18 + .../Scenarios/OracleActivityScenario.cs | 19 + .../Scenarios/OracleBasicScenario.cs | 19 + .../Scenarios/OracleDataScenario.cs | 19 + .../Scenarios/OracleDelayScenario.cs | 23 ++ .../Scenarios/OracleDynamicDataScenario.cs | 19 + .../Scenarios/OracleEventScenario.cs | 19 + .../Scenarios/OracleForeachScenario.cs | 19 + .../Scenarios/OracleForkScenario.cs | 19 + .../Scenarios/OracleIfScenario.cs | 19 + .../Scenarios/OracleRetrySagaScenario.cs | 19 + .../Scenarios/OracleSagaScenario.cs | 19 + .../Scenarios/OracleUserScenario.cs | 19 + .../Scenarios/OracleWhenScenario.cs | 19 + .../Scenarios/OracleWhileScenario.cs | 19 + .../WorkflowCore.Tests.Oracle.csproj | 21 + 29 files changed, 1593 insertions(+), 3 deletions(-) create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/README.md create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj create mode 100644 test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs create mode 100644 test/WorkflowCore.Tests.Oracle/OracleSetup.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj diff --git a/WorkflowCore.sln b/WorkflowCore.sln index e7fb81a2e..25c2016d2 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29509.3 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33424.131 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF47161E-E399-451C-BDE8-E92AAD3BD761}" EndProject @@ -154,6 +154,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.Oracle", "src\providers\WorkflowCore.Persistence.Oracle\WorkflowCore.Persistence.Oracle.csproj", "{635629BC-9D5C-40C6-BBD0-060550ECE290}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.Oracle", "test\WorkflowCore.Tests.Oracle\WorkflowCore.Tests.Oracle.csproj", "{A2837F1C-3740-4375-9069-81AE32C867CA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -376,6 +380,14 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Debug|Any CPU.Build.0 = Debug|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Release|Any CPU.ActiveCfg = Release|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Release|Any CPU.Build.0 = Release|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -438,6 +450,8 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {635629BC-9D5C-40C6-BBD0-060550ECE290} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {A2837F1C-3740-4375-9069-81AE32C867CA} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs new file mode 100644 index 000000000..687109711 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs @@ -0,0 +1,15 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Design; + +namespace WorkflowCore.Persistence.Oracle +{ + public class MigrationContextFactory : IDesignTimeDbContextFactory + { + public OracleContext CreateDbContext(string[] args) + { + return new OracleContext(@"Server=127.0.0.1;Database=myDataBase;Uid=myUsername;Pwd=myPassword;"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs new file mode 100644 index 000000000..7948bc948 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs @@ -0,0 +1,377 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using WorkflowCore.Persistence.Oracle; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + [DbContext(typeof(OracleContext))] + [Migration("20230310125506_InitialDatabase")] + partial class InitialDatabase + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventId") + .HasColumnType("RAW(16)"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("IsProcessed") + .HasColumnType("NUMBER(1)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("ErrorTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("Message") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("Active") + .HasColumnType("NUMBER(1)"); + + b.Property("Children") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ContextItem") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EndTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventPublished") + .HasColumnType("NUMBER(1)"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("NVARCHAR2(50)"); + + b.Property("Outcome") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PersistenceData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("RetryCount") + .HasColumnType("NUMBER(10)"); + + b.Property("Scope") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SleepUntil") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("StartTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("WorkflowId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("AttributeValue") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ExecutionPointerId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("ExecuteTime") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + b.ToTable("ScheduledCommand", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("SubscribeAsOf") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("SubscriptionData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CompleteTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("CreateTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Data") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("NextExecution") + .HasColumnType("NUMBER(19)"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("Version") + .HasColumnType("NUMBER(10)"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs new file mode 100644 index 000000000..9766e7c40 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -0,0 +1,260 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + public partial class InitialDatabase : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Event", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + EventId = table.Column(type: "RAW(16)", nullable: false), + EventName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + EventTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + IsProcessed = table.Column(type: "NUMBER(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Event", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ExecutionError", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + WorkflowId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + ExecutionPointerId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + ErrorTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + Message = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExecutionError", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ScheduledCommand", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + CommandName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + Data = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), + ExecuteTime = table.Column(type: "NUMBER(19)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ScheduledCommand", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "Subscription", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + SubscriptionId = table.Column(type: "RAW(16)", maxLength: 200, nullable: false), + WorkflowId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + StepId = table.Column(type: "NUMBER(10)", nullable: false), + ExecutionPointerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + SubscribeAsOf = table.Column(type: "TIMESTAMP(7)", nullable: false), + SubscriptionData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + ExternalToken = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalWorkerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalTokenExpiry = table.Column(type: "TIMESTAMP(7)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscription", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "Workflow", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + InstanceId = table.Column(type: "RAW(16)", maxLength: 200, nullable: false), + WorkflowDefinitionId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + Version = table.Column(type: "NUMBER(10)", nullable: false), + Description = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), + Reference = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + NextExecution = table.Column(type: "NUMBER(19)", nullable: true), + Data = table.Column(type: "NVARCHAR2(2000)", nullable: true), + CreateTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + CompleteTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + Status = table.Column(type: "NUMBER(10)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Workflow", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ExecutionPointer", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + WorkflowId = table.Column(type: "NUMBER(19)", nullable: false), + Id = table.Column(type: "NVARCHAR2(50)", maxLength: 50, nullable: true), + StepId = table.Column(type: "NUMBER(10)", nullable: false), + Active = table.Column(type: "NUMBER(1)", nullable: false), + SleepUntil = table.Column(type: "TIMESTAMP(7)", nullable: true), + PersistenceData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + StartTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + EndTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + EventName = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + EventPublished = table.Column(type: "NUMBER(1)", nullable: false), + EventData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + StepName = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + RetryCount = table.Column(type: "NUMBER(10)", nullable: false), + Children = table.Column(type: "NVARCHAR2(2000)", nullable: true), + ContextItem = table.Column(type: "NVARCHAR2(2000)", nullable: true), + PredecessorId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + Outcome = table.Column(type: "NVARCHAR2(2000)", nullable: true), + Status = table.Column(type: "NUMBER(10)", nullable: false), + Scope = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExecutionPointer", x => x.PersistenceId); + table.ForeignKey( + name: "FK_ExecutionPointer_Wf_WfId", + column: x => x.WorkflowId, + principalTable: "Workflow", + principalColumn: "PersistenceId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ExtensionAttribute", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + ExecutionPointerId = table.Column(type: "NUMBER(19)", nullable: false), + AttributeKey = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + AttributeValue = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExtensionAttribute", x => x.PersistenceId); + table.ForeignKey( + name: "FK_ExtAttr_ExPtr_ExPtrId", + column: x => x.ExecutionPointerId, + principalTable: "ExecutionPointer", + principalColumn: "PersistenceId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventId", + table: "Event", + column: "EventId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventName_EventKey", + table: "Event", + columns: new[] { "EventName", "EventKey" }); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventTime", + table: "Event", + column: "EventTime"); + + migrationBuilder.CreateIndex( + name: "IX_Event_IsProcessed", + table: "Event", + column: "IsProcessed"); + + migrationBuilder.CreateIndex( + name: "IX_ExecutionPointer_WorkflowId", + table: "ExecutionPointer", + column: "WorkflowId"); + + migrationBuilder.CreateIndex( + name: "IX_ExtensionAttribute_ExecutionPointerId", + table: "ExtensionAttribute", + column: "ExecutionPointerId"); + + migrationBuilder.CreateIndex( + name: "IX_ScheduledCommand_CommandName_Data", + table: "ScheduledCommand", + columns: new[] { "CommandName", "Data" }, + unique: true, + filter: "\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_ScheduledCommand_ExecuteTime", + table: "ScheduledCommand", + column: "ExecuteTime"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_EventKey", + table: "Subscription", + column: "EventKey"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_EventName", + table: "Subscription", + column: "EventName"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_SubscriptionId", + table: "Subscription", + column: "SubscriptionId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Workflow_InstanceId", + table: "Workflow", + column: "InstanceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Workflow_NextExecution", + table: "Workflow", + column: "NextExecution"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Event"); + + migrationBuilder.DropTable( + name: "ExecutionError"); + + migrationBuilder.DropTable( + name: "ExtensionAttribute"); + + migrationBuilder.DropTable( + name: "ScheduledCommand"); + + migrationBuilder.DropTable( + name: "Subscription"); + + migrationBuilder.DropTable( + name: "ExecutionPointer"); + + migrationBuilder.DropTable( + name: "Workflow"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs new file mode 100644 index 000000000..63a882eef --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -0,0 +1,375 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using WorkflowCore.Persistence.Oracle; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + [DbContext(typeof(OracleContext))] + partial class OracleContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventId") + .HasColumnType("RAW(16)"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("IsProcessed") + .HasColumnType("NUMBER(1)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("ErrorTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("Message") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("Active") + .HasColumnType("NUMBER(1)"); + + b.Property("Children") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ContextItem") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EndTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventPublished") + .HasColumnType("NUMBER(1)"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("NVARCHAR2(50)"); + + b.Property("Outcome") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PersistenceData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("RetryCount") + .HasColumnType("NUMBER(10)"); + + b.Property("Scope") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SleepUntil") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("StartTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("WorkflowId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("AttributeValue") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ExecutionPointerId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("ExecuteTime") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + b.ToTable("ScheduledCommand", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("SubscribeAsOf") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("SubscriptionData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CompleteTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("CreateTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Data") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("NextExecution") + .HasColumnType("NUMBER(19)"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("Version") + .HasColumnType("NUMBER(10)"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs new file mode 100644 index 000000000..b8fadcdf7 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Persistence.EntityFramework.Models; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public class OracleContext : WorkflowDbContext + { + private readonly string _connectionString; + private readonly Action _oracleOptionsAction; + + public OracleContext(string connectionString, Action oracleOptionsAction = null) + { + _connectionString = connectionString; + _oracleOptionsAction = oracleOptionsAction; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + optionsBuilder.UseOracle(_connectionString, _oracleOptionsAction); + } + + protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) + { + builder.ToTable("Subscription"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) + { + builder.ToTable("Workflow"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExecutionPointer"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExecutionError"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExtensionAttribute"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureEventStorage(EntityTypeBuilder builder) + { + builder.ToTable("Event"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs new file mode 100644 index 000000000..54c70d6dc --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Infrastructure; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Persistence.EntityFramework.Interfaces; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public class OracleContextFactory : IWorkflowDbContextFactory + { + private readonly string _connectionString; + private readonly Action _oracleOptionsAction; + + public OracleContextFactory(string connectionString, Action oracleOptionsAction = null) + { + _connectionString = connectionString; + _oracleOptionsAction = oracleOptionsAction; + } + + public WorkflowDbContext Build() + { + return new OracleContext(_connectionString, _oracleOptionsAction); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/README.md b/src/providers/WorkflowCore.Persistence.Oracle/README.md new file mode 100644 index 000000000..0e4957eea --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/README.md @@ -0,0 +1,19 @@ +# Oracle Persistence provider for Workflow Core + +Provides support to persist workflows running on [Workflow Core](../../README.md) to an Oracle database. + +## Installing + +Install the NuGet package "WorkflowCore.Persistence.Oracle" + +``` +PM> Install-Package WorkflowCore.Persistence.Oracle -Pre +``` + +## Usage + +Use the .UseOracle extension method when building your service provider. + +```C# +services.AddWorkflow(x => x.UseOracle(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); +``` diff --git a/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..4a46b0e5c --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.DependencyInjection; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public static class ServiceCollectionExtensions + { + public static WorkflowOptions UseOracle(this WorkflowOptions options, string connectionString, bool canCreateDB, bool canMigrateDB, Action mysqlOptionsAction = null) + { + options.UsePersistence(sp => new EntityFrameworkPersistenceProvider(new OracleContextFactory(connectionString, mysqlOptionsAction), canCreateDB, canMigrateDB)); + options.Services.AddTransient(sp => new WorkflowPurger(new OracleContextFactory(connectionString, mysqlOptionsAction))); + return options; + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj new file mode 100644 index 000000000..1c80bad68 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj @@ -0,0 +1,43 @@ + + + + Workflow Core Oracle Persistence Provider + 1.0.0 + Christian Jundt + net6.0 + WorkflowCore.Persistence.Oracle + WorkflowCore.Persistence.Oracle + workflow;.NET;Core;state machine;WorkflowCore;Oracle + https://github.com/danielgerlag/workflow-core + https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md + git + https://github.com/danielgerlag/workflow-core.git + false + false + false + Provides support to persist workflows running on Workflow Core to a Oracle database. + + + + + all + runtime; build; native; contentfiles; analyzers + + + 6.21.61 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs index 1e082f4db..a5819d2fa 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs @@ -43,7 +43,7 @@ public void Build(IWorkflowBuilder builder) public ActivityScenario() { - Setup(); + Setup(); //NOTE cjundt [10/03/2023] setup shouldn't be here in constructor. It prevents from using ICollectionFixture data. } [Fact] diff --git a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs new file mode 100644 index 000000000..c4445f005 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs @@ -0,0 +1,25 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Persistence.EntityFramework.Services; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; +using WorkflowCore.UnitTests; +using Xunit; +using Xunit.Abstractions; + +namespace WorkflowCore.Tests.Oracle +{ + [Collection("Oracle collection")] + public class OraclePersistenceProviderFixture : BasePersistenceFixture + { + private readonly IPersistenceProvider _subject; + protected override IPersistenceProvider Subject => _subject; + + public OraclePersistenceProviderFixture(OracleDockerSetup dockerSetup, ITestOutputHelper output) + { + output.WriteLine($"Connecting on {OracleDockerSetup.ConnectionString}"); + _subject = new EntityFrameworkPersistenceProvider(new OracleContextFactory(OracleDockerSetup.ConnectionString), true, true); + _subject.EnsureStoreExists(); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/OracleSetup.cs b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs new file mode 100644 index 000000000..8b35d9aa2 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle +{ + public class OracleDockerSetup : IAsyncLifetime + { + public static string ConnectionString => "Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORCLPDB1) ) );User ID=TEST_WF;Password=test;"; + + public async Task InitializeAsync() + { + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + } + + [CollectionDefinition("Oracle collection")] + public class OracleCollection : ICollectionFixture + { + } +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs b/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..24072c66f --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WorkflowCore.Tests.Oracle")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8c2bd4d2-43ec-4930-9364-cda938c01803")] diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs new file mode 100644 index 000000000..eeae8ea66 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleActivityScenario : ActivityScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs new file mode 100644 index 000000000..8cb898583 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleBasicScenario : BasicScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs new file mode 100644 index 000000000..f71630c93 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDataScenario : DataIOScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs new file mode 100644 index 000000000..55062f0c3 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDelayScenario : DelayScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UseOracle(OracleDockerSetup.ConnectionString, true, true); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs new file mode 100644 index 000000000..e59f51d51 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDynamicDataScenario : DynamicDataIOScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs new file mode 100644 index 000000000..ac987c341 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleEventScenario : EventScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs new file mode 100644 index 000000000..fb2fcc965 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleForeachScenario : ForeachScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs new file mode 100644 index 000000000..d525de700 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleForkScenario : ForkScenario + { + protected override void Configure(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs new file mode 100644 index 000000000..c090f89d1 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleIfScenario : IfScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs new file mode 100644 index 000000000..01c651a7c --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleRetrySagaScenario : RetrySagaScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs new file mode 100644 index 000000000..7775638c2 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleSagaScenario : SagaScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs new file mode 100644 index 000000000..0e5861f6d --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleUserScenario : UserScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs new file mode 100644 index 000000000..b8671695e --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleWhenScenario : WhenScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs new file mode 100644 index 000000000..0b4b01467 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleWhileScenario : WhileScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj new file mode 100644 index 000000000..db77aa957 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + WorkflowCore.Tests.Oracle + WorkflowCore.Tests.Oracle + true + false + false + false + + + + + + + + + + + From f63e7db6e2022c8115ecdd86195d458bae72ff85 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Fri, 2 Jun 2023 21:01:24 +0200 Subject: [PATCH 2/3] La colonne ExternalToken est trop petite --- .../Migrations/20230310125506_InitialDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs index 9766e7c40..cab8aee7c 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -72,7 +72,7 @@ protected override void Up(MigrationBuilder migrationBuilder) EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), SubscribeAsOf = table.Column(type: "TIMESTAMP(7)", nullable: false), SubscriptionData = table.Column(type: "NVARCHAR2(2000)", nullable: true), - ExternalToken = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalToken = table.Column(type: "NVARCHAR2(400)", maxLength: 400, nullable: true), ExternalWorkerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), ExternalTokenExpiry = table.Column(type: "TIMESTAMP(7)", nullable: true) }, From c6f192de9a934dce65a803c1f39b8b11ddcb5bf4 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Thu, 8 Jun 2023 11:25:37 +0200 Subject: [PATCH 3/3] Workflow.Data converti en CLOB --- .../Migrations/20230310125506_InitialDatabase.cs | 2 +- .../Migrations/OracleContextModelSnapshot.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs index cab8aee7c..e758e161d 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -93,7 +93,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Description = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), Reference = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), NextExecution = table.Column(type: "NUMBER(19)", nullable: true), - Data = table.Column(type: "NVARCHAR2(2000)", nullable: true), + Data = table.Column(type: "CLOB", nullable: true), CreateTime = table.Column(type: "TIMESTAMP(7)", nullable: false), CompleteTime = table.Column(type: "TIMESTAMP(7)", nullable: true), Status = table.Column(type: "NUMBER(10)", nullable: false) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs index 63a882eef..6d600dcc5 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -301,7 +301,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TIMESTAMP(7)"); b.Property("Data") - .HasColumnType("NVARCHAR2(2000)"); + .HasColumnType("CLOB"); b.Property("Description") .HasMaxLength(500)