Update EF Core DB Context types to accept non-generic DbOptions

This commit is contained in:
Sipke Schoorstra 2021-01-27 10:32:15 +01:00
parent d5b30b6044
commit 32bf393026
13 changed files with 47 additions and 295 deletions

View file

@ -1,29 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
{
public abstract class DesignTimeDbContextFactoryBase<TDbContext> : IDesignTimeDbContextFactory<TDbContext> where TDbContext : DbContext
{
public TDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<TDbContext>();
var migrationAssembly = typeof(TDbContext).Assembly.FullName;
var connectionString = Environment.GetEnvironmentVariable("EF_CONNECTIONSTRING");
if(connectionString == null)
{
var providerName = typeof(TDbContext).Name.Replace("Context", "");
throw new InvalidOperationException($"Set the EF_CONNECTIONSTRING environment variable to a valid {providerName} connection string.");
}
optionsBuilder.UseSqlite(
connectionString,
x => x.MigrationsAssembly(migrationAssembly)
);
return (TDbContext)Activator.CreateInstance(typeof(TDbContext), optionsBuilder.Options);
}
}
}

View file

@ -4,7 +4,7 @@ namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
{
public class MySqlContext : ElsaContext
{
public MySqlContext(DbContextOptions<MySqlContext> options) : base(options)
public MySqlContext(DbContextOptions options) : base(options)
{
}
}

View file

@ -12,9 +12,9 @@ namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
var migrationAssembly = typeof(MySqlContext).Assembly.FullName;
var connectionString = Environment.GetEnvironmentVariable("EF_CONNECTIONSTRING");
if(connectionString == null)
if (connectionString == null)
throw new InvalidOperationException("Set the EF_CONNECTIONSTRING environment variable to a valid MySQL connection string. E.g. SET EF_CONNECTIONSTRING=Server=localhost;Database=Elsa;User=sa;Password=Secret_password123!;");
optionsBuilder.UseMySql(
new MySqlServerVersion(ServerVersion.AutoDetect(connectionString)),
x => x.MigrationsAssembly(migrationAssembly)

View file

@ -4,7 +4,7 @@ namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
{
public class PostgreSqlContext : ElsaContext
{
public PostgreSqlContext(DbContextOptions<PostgreSqlContext> options) : base(options)
public PostgreSqlContext(DbContextOptions options) : base(options)
{
}
}

View file

@ -4,7 +4,7 @@ namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
{
public class SqlServerContext : ElsaContext
{
public SqlServerContext(DbContextOptions<SqlServerContext> options) : base(options)
public SqlServerContext(DbContextOptions options) : base(options)
{
}
}

View file

@ -4,7 +4,7 @@ namespace Elsa.Persistence.EntityFrameworkCore.DbContexts
{
public class SqliteContext : ElsaContext
{
public SqliteContext(DbContextOptions<SqliteContext> options) : base(options)
public SqliteContext(DbContextOptions options) : base(options)
{
}
}

View file

@ -2,6 +2,7 @@ using System;
using Elsa.Extensions;
using Elsa.Mapping;
using Elsa.Persistence.EntityFrameworkCore.DbContexts;
using Elsa.Persistence.EntityFrameworkCore.HostedServices;
using Elsa.Persistence.EntityFrameworkCore.Mapping;
using Elsa.Persistence.EntityFrameworkCore.Services;
using Microsoft.EntityFrameworkCore;
@ -14,7 +15,8 @@ namespace Elsa.Persistence.EntityFrameworkCore.Extensions
public static EntityFrameworkCoreElsaBuilder AddEntityFrameworkCoreProvider<TElsaContext>(
this ElsaBuilder configuration,
Action<DbContextOptionsBuilder> configureOptions,
bool usePooling = true)
bool usePooling = true,
bool autoRunMigrations = false)
where TElsaContext : ElsaContext
{
var services = configuration.Services;
@ -26,6 +28,9 @@ namespace Elsa.Persistence.EntityFrameworkCore.Extensions
services
.AddMapperProfile<NodaTimeProfile>(ServiceLifetime.Singleton)
.AddMapperProfile<EntitiesProfile>(ServiceLifetime.Singleton);
if (autoRunMigrations)
services.AddHostedService<RunMigrations>();
return new EntityFrameworkCoreElsaBuilder(configuration.Services);
}

View file

@ -0,0 +1,28 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Persistence.EntityFrameworkCore.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Elsa.Persistence.EntityFrameworkCore.HostedServices
{
/// <summary>
/// Executes EF Core migrations.
/// </summary>
public class RunMigrations : IHostedService
{
private readonly IServiceProvider serviceProvider;
public RunMigrations(IServiceProvider serviceProvider) => this.serviceProvider = serviceProvider;
public async Task StartAsync(CancellationToken cancellationToken)
{
using var scope = serviceProvider.CreateScope();
var elsaContext = scope.ServiceProvider.GetRequiredService<ElsaContext>();
await elsaContext.Database.MigrateAsync(cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}

View file

@ -11,11 +11,11 @@ This list of sample implementations showcase a variety of workflows using ELSA.
7. [Document Approval](Sample07) - Example of a Document Approval workflow.
8. [Create and Handle Orders](Sample08) - Example of a workflow that creates and handles orders. Uses Mass Transit and RabbitMq.
9. [Calculator: Defined in Json](Sample9) - A simple console program that loads & executes a workflow designed with the HTML5 workflow designer.
10. [Hellow World: YesSql](Sample10) - A simple demonstration of using YesSql persistence providers.
10. [Hello World: YesSql](Sample10) - A simple demonstration of using YesSql persistence providers.
11. [Correlation](Sample11) - Demonstrates workflow correlation.
12. [User Task](Sample12) - Demonstrates workflow correlation & user tasks.
13. [Activity Output](Sample13) - A strongly-typed workflows program demonstrating scripting, and branching.
14. [Hellow World: Entity Framework Core](Sample14) - A simple demonstration of using Entity Framework Core persistence providers.
14. [Hello World: Entity Framework Core](Sample14) - A simple demonstration of using Entity Framework Core persistence providers.
15. [Hello World: MongoDb](Sample15) - A simple demonstration of using the MongoDB persistence providers. Docker(optional)
16. [ELSA Dashboard: Web App, MongoDb Persistence](Sample16) - ELSA Dashboard MVC wep application.
17. [Create Person: Console Application](Sample17) - Example of a workflow that creates a Person entity.

View file

@ -1,95 +0,0 @@
// <auto-generated />
using System;
using Elsa.Persistence.EntityFrameworkCore;
using Elsa.Persistence.EntityFrameworkCore.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Sample14.Migrations
{
[DbContext(typeof(ElsaContext))]
[Migration("20191021193326_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
modelBuilder.Entity("Elsa.Persistence.EntityFrameworkCore.Documents.WorkflowDefinitionVersionDocument", b =>
{
b.Property<string>("Id");
b.Property<string>("Activities");
b.Property<string>("Connections");
b.Property<string>("DefinitionId");
b.Property<string>("Description");
b.Property<bool>("IsDisabled");
b.Property<bool>("IsLatest");
b.Property<bool>("IsPublished");
b.Property<bool>("IsSingleton");
b.Property<string>("Name");
b.Property<string>("Variables");
b.Property<int>("Version");
b.HasKey("Id");
b.ToTable("WorkflowDefinitionVersions");
});
modelBuilder.Entity("Elsa.Persistence.EntityFrameworkCore.Documents.WorkflowInstanceDocument", b =>
{
b.Property<string>("Id");
b.Property<DateTime?>("AbortedAt");
b.Property<string>("Activities");
b.Property<string>("BlockingActivities");
b.Property<string>("CorrelationId");
b.Property<DateTime>("CreatedAt");
b.Property<string>("DefinitionId");
b.Property<string>("ExecutionLog");
b.Property<string>("Fault");
b.Property<DateTime?>("FaultedAt");
b.Property<DateTime?>("FinishedAt");
b.Property<string>("Input");
b.Property<string>("Scopes");
b.Property<DateTime?>("StartedAt");
b.Property<string>("Status")
.IsRequired();
b.Property<int>("Version");
b.HasKey("Id");
b.ToTable("WorkflowInstances");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,68 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Sample14.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "WorkflowDefinitionVersions",
columns: table => new
{
Id = table.Column<string>(nullable: false),
DefinitionId = table.Column<string>(nullable: true),
Version = table.Column<int>(nullable: false),
Name = table.Column<string>(nullable: true),
Description = table.Column<string>(nullable: true),
Activities = table.Column<string>(nullable: true),
Connections = table.Column<string>(nullable: true),
Variables = table.Column<string>(nullable: true),
IsSingleton = table.Column<bool>(nullable: false),
IsDisabled = table.Column<bool>(nullable: false),
IsPublished = table.Column<bool>(nullable: false),
IsLatest = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_WorkflowDefinitionVersions", x => x.Id);
});
migrationBuilder.CreateTable(
name: "WorkflowInstances",
columns: table => new
{
Id = table.Column<string>(nullable: false),
DefinitionId = table.Column<string>(nullable: true),
Version = table.Column<int>(nullable: false),
Status = table.Column<string>(nullable: false),
CorrelationId = table.Column<string>(nullable: true),
CreatedAt = table.Column<DateTime>(nullable: false),
StartedAt = table.Column<DateTime>(nullable: true),
FinishedAt = table.Column<DateTime>(nullable: true),
FaultedAt = table.Column<DateTime>(nullable: true),
AbortedAt = table.Column<DateTime>(nullable: true),
Activities = table.Column<string>(nullable: true),
Scopes = table.Column<string>(nullable: true),
Input = table.Column<string>(nullable: true),
BlockingActivities = table.Column<string>(nullable: true),
ExecutionLog = table.Column<string>(nullable: true),
Fault = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_WorkflowInstances", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "WorkflowDefinitionVersions");
migrationBuilder.DropTable(
name: "WorkflowInstances");
}
}
}

View file

@ -1,91 +0,0 @@
// <auto-generated />
using System;
using Elsa.Persistence.EntityFrameworkCore.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace Sample14.Migrations
{
[DbContext(typeof(ElsaContext))]
internal partial class ElsaContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
modelBuilder.Entity("Elsa.Persistence.EntityFrameworkCore.Documents.WorkflowDefinitionVersionDocument", b =>
{
b.Property<string>("Id");
b.Property<string>("Activities");
b.Property<string>("Connections");
b.Property<string>("DefinitionId");
b.Property<string>("Description");
b.Property<bool>("IsDisabled");
b.Property<bool>("IsLatest");
b.Property<bool>("IsPublished");
b.Property<bool>("IsSingleton");
b.Property<string>("Name");
b.Property<string>("Variables");
b.Property<int>("Version");
b.HasKey("Id");
b.ToTable("WorkflowDefinitionVersions");
});
modelBuilder.Entity("Elsa.Persistence.EntityFrameworkCore.Documents.WorkflowInstanceDocument", b =>
{
b.Property<string>("Id");
b.Property<DateTime?>("AbortedAt");
b.Property<string>("Activities");
b.Property<string>("BlockingActivities");
b.Property<string>("CorrelationId");
b.Property<DateTime>("CreatedAt");
b.Property<string>("DefinitionId");
b.Property<string>("ExecutionLog");
b.Property<string>("Fault");
b.Property<DateTime?>("FaultedAt");
b.Property<DateTime?>("FinishedAt");
b.Property<string>("Input");
b.Property<string>("Scopes");
b.Property<DateTime?>("StartedAt");
b.Property<string>("Status")
.IsRequired();
b.Property<int>("Version");
b.HasKey("Id");
b.ToTable("WorkflowInstances");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -28,7 +28,7 @@ namespace Sample14
await startupRunner.StartupAsync();
// Create a workflow definition.
var registry = services.GetService<IWorkflowRegistry>();
var registry = services.GetRequiredService<IWorkflowRegistry>();
var workflowDefinition = await registry.GetWorkflowDefinitionAsync<HelloWorldWorkflow>();
// Mark this definition as the "latest" version.
@ -70,9 +70,11 @@ namespace Sample14
{
return new ServiceCollection()
.AddElsa(
x => x.AddEntityFrameworkStores<SqliteContext>(
x => x.AddEntityFrameworkCoreProvider<SqliteContext>(
options => options
.UseSqlite(@"Data Source=c:\data\elsa.entity-framework-core.db;Cache=Shared")))
.UseSqlite(
@"Data Source=c:\data\elsa.entity-framework-core.db;Cache=Shared",
db => db.MigrationsAssembly(typeof(SqliteContextFactory).Assembly.GetName().Name)), autoRunMigrations: true))
.AddStartupRunner()
.AddConsoleActivities()
.AddWorkflow<HelloWorldWorkflow>()