Skip to content

Commit

Permalink
SQLite implementation (#50)
Browse files Browse the repository at this point in the history
* Draft version of SQLite implementation with integration test

* Added a static reference for every table name in SQLite project, this is to keep all table names consistent across database types

* Added SQLite migration test

* Removed shouldly import

* Assert.Null instead of  Assert.NotNull on recording exception

* Added publish package entry for SQLite

* Forgot a prefix in QuartzTriggerConfiguration

* Added integration test for SQLite which ensure the created dbcontext can be used as a JobStore

* Removed the static table name references from the Entities

* Fixed rebase merge error

* Capitalised all column names for SQLite

* Changed the signature of UseSQLite to have optional prefix and schema parameters

* Removed nullable strings from the EntityConfiguration and corrected readonly name format

* Organised the testing files into individual folder per database type

* Changed signature for the UsePostgreSql() to use prefix and schema as parameters

* Changed all column names to uppercase for MySQL entity configurations

* Changed signature for the UseMySql() to use prefix as parameter

* Corrected namespace for MySql configurations

* Corrected namespace for MySql configurations
Changed signature for the UseSqlServer() to use prefix and schema as parameters

* Removed obsolete UsePrefix and UseSchema

* Updated Readme to reflect current supported databases and made it more clear with examples

* Updated the csproj of SQLite project

* Made all name spacing consistent to just `AppAny.Quartz.EntityFrameworkCore.Migrations.{{ Provider }}`

* Removed extra line

* Added clarification that prefix and schema can be passed as parameters

* Added default parameter value for schema in UseSqlite() and UseSqlServer()
  • Loading branch information
JasonLandbridge authored Dec 15, 2022
1 parent 31cf2dd commit b78888b
Show file tree
Hide file tree
Showing 49 changed files with 1,185 additions and 247 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ jobs:
env:
PROJECT: src/AppAny.Quartz.EntityFrameworkCore.Migrations.MySql/AppAny.Quartz.EntityFrameworkCore.Migrations.MySql.csproj
VERSION: ${{ steps.release.outputs.tag }}

- name: Package | Publish | SQLite
run: dotnet pack -c Release -o ./pack /p:Version=$VERSION $PROJECT
env:
PROJECT: src/AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite/AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite.csproj
VERSION: ${{ steps.release.outputs.tag }}

- name: Package | Publish | SqlServer
run: dotnet pack -c Release -o ./pack /p:Version=$VERSION $PROJECT
Expand Down
15 changes: 15 additions & 0 deletions AppAny.Quartz.EntityFrameworkCore.Migrations.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppAny.Quartz.EntityFramewo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer", "src\AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer\AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer.csproj", "{81D33747-2D69-4E32-B2F3-1A0C7960FB9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite", "src\AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite\AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite.csproj", "{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -87,6 +89,18 @@ Global
{81D33747-2D69-4E32-B2F3-1A0C7960FB9D}.Release|x64.Build.0 = Release|Any CPU
{81D33747-2D69-4E32-B2F3-1A0C7960FB9D}.Release|x86.ActiveCfg = Release|Any CPU
{81D33747-2D69-4E32-B2F3-1A0C7960FB9D}.Release|x86.Build.0 = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|x64.ActiveCfg = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|x64.Build.0 = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|x86.ActiveCfg = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Debug|x86.Build.0 = Debug|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|Any CPU.Build.0 = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|x64.ActiveCfg = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|x64.Build.0 = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|x86.ActiveCfg = Release|Any CPU
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -96,6 +110,7 @@ Global
{B93044E6-2EA1-4D10-932D-7D232DB02C76} = {6AAE677C-A38E-4AD0-951B-4E64D91EE928}
{47E591EA-37FC-438D-96E0-EBC609BFDFA9} = {F87C6291-1953-4FD8-AE97-530A9B63B6B0}
{C6D9078D-F57B-43A9-84A3-60882741022D} = {6AAE677C-A38E-4AD0-951B-4E64D91EE928}
{B43D24EE-F42A-4A0A-BE81-9431ED219BBF} = {6AAE677C-A38E-4AD0-951B-4E64D91EE928}
{81D33747-2D69-4E32-B2F3-1A0C7960FB9D} = {6AAE677C-A38E-4AD0-951B-4E64D91EE928}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
118 changes: 95 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,127 @@
![Tests](https://github.com/appany/AppAny.Quartz.EntityFrameworkCore.Migrations/workflows/Tests/badge.svg)
[![codecov](https://codecov.io/gh/appany/AppAny.Quartz.EntityFrameworkCore.Migrations/branch/main/graph/badge.svg?token=589PU3Y1S9)](https://codecov.io/gh/appany/AppAny.Quartz.EntityFrameworkCore.Migrations)

⚡️ This library handles schema migrations for Quartz.NET using EntityFrameworkCore migrations toolkit with one line of configuration ⚡️
⚡️ This library handles schema creation and migrations for Quartz.NET using EntityFrameworkCore migrations toolkit with one line of configuration ⚡️

## 💡 Supported drivers 💡

- [x] [MySQL](https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql)
- [x] [PostgreSQL](https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL)
- [x] [SQLite](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Sqlite)
- [x] [SQLServer](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.SqlServer)

🚧 Feel free to **create as issue** for driver support 🚧

## 🔧 Installation 🔧

### MySql

```bash
$> dotnet add package AppAny.Quartz.EntityFrameworkCore.Migrations.PostgreSQL
dotnet add package AppAny.Quartz.EntityFrameworkCore.Migrations.MySql
```

## 💡 Supported drivers 💡
### PostgreSQL

```bash
dotnet add package AppAny.Quartz.EntityFrameworkCore.Migrations.PostgreSQL
```

### SQLite

```bash
dotnet add package AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite
```

### SqlServer

```bash
dotnet add package AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer
```



- [x] [PostgreSQL](https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL)
- [x] [MySQL](Pomelo.EntityFrameworkCore.MySql)
- [x] [SQLServer](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.SqlServer)

🚧 Feel free to **create as issue** for driver support 🚧

## 🎨 Usage 🎨

✅ Configure `DbContext`
✅ Configure the `DbContext` that will hold the Quartz.NET tables
```cs
public class DatabaseContext : DbContext
{
// ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Prefix and schema can be passed as parameters
// Adds Quartz.NET MySql schema to EntityFrameworkCore
modelBuilder.AddQuartz(builder => builder.UseMySql());

// Adds Quartz.NET PostgreSQL schema to EntityFrameworkCore
modelBuilder.AddQuartz(builder => builder
.UsePostgreSql()
.UseSchema("quartz")
.UseNoPrefix());
modelBuilder.AddQuartz(builder => builder.UsePostgreSql());

// Adds Quartz.NET SQLite schema to EntityFrameworkCore
modelBuilder.AddQuartz(builder => builder.UseSQLite());

// Adds Quartz.NET SqlServer schema to EntityFrameworkCore
modelBuilder.AddQuartz(builder => builder.UseSqlServer());
}
}
```

✅ Configure `Quartz.NET`
```cs
storeOptions.UsePostgreSql(postgresOptions =>
✅ (Optional) [ASP.NET Core Integration](https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/aspnet-core-integration.html#using) Configuration

```csharp
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
postgresOptions.UseDriverDelegate<PostgreSQLDelegate>();
postgresOptions.ConnectionString = ...;
postgresOptions.TablePrefix = ...;
});
services.AddQuartz(q =>
{
q.UsePersistentStore(c =>
{
// Use for MySQL database
c.UseMySql(mysqlOptions =>
{
mysqlOptions.UseDriverDelegate<MySQLDelegate>();
mysqlOptions.ConnectionString = ...;
mysqlOptions.TablePrefix = ...;
});

// Use for PostgresSQL database
c.UsePostgres(postgresOptions =>
{
postgresOptions.UseDriverDelegate<PostgreSQLDelegate>();
postgresOptions.ConnectionString = ...;
postgresOptions.TablePrefix = ...;
});

// Use for SQLite database
c.UseSQLite(sqlLiteOptions =>
{
sqlLiteOptions.UseDriverDelegate<SQLiteDelegate>();
sqlLiteOptions.ConnectionString = ...;
sqlLiteOptions.TablePrefix = ...;
});

// Use for SqlServer database
c.UseSqlServer(sqlServerOptions =>
{
sqlServerOptions.UseDriverDelegate<SqlServerDelegate>();
sqlServerOptions.ConnectionString = ...;
sqlServerOptions.TablePrefix = ...;
});
});
});
}

```

✅ Add EntityFrameworkCore migration with Quartz.NET schema `dotnet ef migrations add AddQuartz` and:
## 🚩 Finish 🚩

✅ Add EntityFrameworkCore migration with Quartz.NET schema `dotnet ef migrations add AddQuartz` and then

🚩 Add in-process migration using `databaseContext.Database.MigrateAsync()`
* 🚩 Add in-process migration using `databaseContext.Database.MigrateAsync()`

🚩 Add out-of-process migration using `dotnet ef database update`
* 🚩 Add out-of-process migration using `dotnet ef database update`

🚩 Extract SQL for your migration tool `dotnet ef migrations script PreviousMigration AddQuartz`
* 🚩 Extract SQL for your migration tool `dotnet ef migrations script PreviousMigration AddQuartz`
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=entitytypeconfigurations/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@ public QuartzBlobTriggerEntityTypeConfiguration(string? prefix)

public void Configure(EntityTypeBuilder<QuartzBlobTrigger> builder)
{
builder.ToTable($"{prefix}blob_triggers");
builder.ToTable($"{prefix}BLOB_TRIGGERS");

builder.HasKey(x => new { x.SchedulerName, x.TriggerName, x.TriggerGroup });

builder.Property(x => x.SchedulerName)
.HasColumnName("sched_name")
.HasColumnName("SCHED_NAME")
.HasColumnType("varchar(120)")
.IsRequired();

builder.Property(x => x.TriggerName)
.HasColumnName("trigger_name")
.HasColumnName("TRIGGER_NAME")
.HasColumnType("varchar(200)")
.IsRequired();

builder.Property(x => x.TriggerGroup)
.HasColumnName("trigger_group")
.HasColumnName("TRIGGER_GROUP")
.HasColumnType("varchar(200)")
.IsRequired();

builder.Property(x => x.BlobData)
.HasColumnName("blob_data")
.HasColumnName("BLOB_DATA")
.HasColumnType("blob");

builder.HasOne(x => x.Trigger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ public QuartzCalendarEntityTypeConfiguration(string? prefix)

public void Configure(EntityTypeBuilder<QuartzCalendar> builder)
{
builder.ToTable($"{prefix}calendars");
builder.ToTable($"{prefix}CALENDARS");

builder.HasKey(x => new { x.SchedulerName, x.CalendarName });

builder.Property(x => x.SchedulerName)
.HasColumnName("sched_name")
.HasColumnName("SCHED_NAME")
.HasColumnType("varchar(120)")
.IsRequired();

builder.Property(x => x.CalendarName)
.HasColumnName("calendar_name")
.HasColumnName("CALENDAR_NAME")
.HasColumnType("varchar(200)")
.IsRequired();

builder.Property(x => x.Calendar)
.HasColumnName("calendar")
.HasColumnName("CALENDAR")
.HasColumnType("blob")
.IsRequired();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,32 @@ public QuartzCronTriggerEntityTypeConfiguration(string? prefix)

public void Configure(EntityTypeBuilder<QuartzCronTrigger> builder)
{
builder.ToTable($"{prefix}cron_triggers");
builder.ToTable($"{prefix}CRON_TRIGGERS");

builder.HasKey(x => new { x.SchedulerName, x.TriggerName, x.TriggerGroup });

builder.Property(x => x.SchedulerName)
.HasColumnName("sched_name")
.HasColumnName("SCHED_NAME")
.HasColumnType("varchar(120)")
.IsRequired();

builder.Property(x => x.TriggerName)
.HasColumnName("trigger_name")
.HasColumnName("TRIGGER_NAME")
.HasColumnType("varchar(200)")
.IsRequired();

builder.Property(x => x.TriggerGroup)
.HasColumnName("trigger_group")
.HasColumnName("TRIGGER_GROUP")
.HasColumnType("varchar(200)")
.IsRequired();

builder.Property(x => x.CronExpression)
.HasColumnName("cron_expression")
.HasColumnName("CRON_EXPRESSION")
.HasColumnType("varchar(120)")
.IsRequired();

builder.Property(x => x.TimeZoneId)
.HasColumnName("time_zone_id")
.HasColumnName("TIME_ZONE_ID")
.HasColumnType("varchar(80)");

builder.HasOne(x => x.Trigger)
Expand Down
Loading

0 comments on commit b78888b

Please sign in to comment.