EasyCore.Quartz.Oracle
8.3.0
dotnet add package EasyCore.Quartz.Oracle --version 8.3.0
NuGet\Install-Package EasyCore.Quartz.Oracle -Version 8.3.0
<PackageReference Include="EasyCore.Quartz.Oracle" Version="8.3.0" />
<PackageVersion Include="EasyCore.Quartz.Oracle" Version="8.3.0" />
<PackageReference Include="EasyCore.Quartz.Oracle" />
paket add EasyCore.Quartz.Oracle --version 8.3.0
#r "nuget: EasyCore.Quartz.Oracle, 8.3.0"
#:package EasyCore.Quartz.Oracle@8.3.0
#addin nuget:?package=EasyCore.Quartz.Oracle&version=8.3.0
#tool nuget:?package=EasyCore.Quartz.Oracle&version=8.3.0
โฑ๏ธ EasyCore.Quartz
EasyCore.Quartz is a production-oriented job scheduling library for .NET 8. Built on Quartz.NET, it provides attribute-based jobs, an English ops dashboard, REST management APIs, dynamic HTTP jobs, and persistence with clustering for MySQL / SQL Server / PostgreSQL / Oracle.
๐ Language
- Chinese: README.md
- English (this document)
๐ Table of Contents
Part I โ Overview & Architecture
Part II โ Getting Started
Part III โ Dashboard ยท REST ยท HTTP Jobs
Part IV โ Persistence & Production
- 12. Database Configuration
- 13. Clustering & Concurrency
- 14. Demo Projects
- 15. Migrating from older versions
- 16. Production Checklist
- 17. FAQ
- 18. License
1. Positioning
EasyCore.Quartz makes Quartz easy, operable, and production-safe in ASP.NET Core:
| Pain point | EasyCore.Quartz approach |
|---|---|
| Manual job wiring | IEasyCoreJob + [EasyCoreCron] auto-discovery |
| No ops UI | Optional package EasyCore.Quartz.Dashboard (/easy-quartz) |
| Split management APIs | Shared IJobManagementService (Dashboard + REST) |
| Multi-DB persistence | Separate MySQL / SQL Server / PostgreSQL / Oracle packages |
| Swallowed exceptions | JobWrapper logs and rethrows |
| Accidental public exposure | Dashboard Basic Auth; username/password required |
1.1 Design Principles
| Principle | Meaning |
|---|---|
| Low friction | One extension method + one attribute to get running |
| Operable | Full dashboard: Overview / Jobs / History / โฆ |
| Pluggable storage | Core and DB packages are separate |
| Failure-aware | Exceptions propagate; History records outcomes |
| Secure by default | Empty authorization list โ reject dashboard access |
1.2 Repository Layout
EasyCore.Quartz/
โโโ src/
โ โโโ EasyCore.Quartz/ # Core: discovery, management, REST, History
โ โโโ EasyCore.Quartz.Dashboard/ # English ops dashboard
โ โโโ EasyCore.Quartz.MySql/
โ โโโ EasyCore.Quartz.SqlServer/
โ โโโ EasyCore.Quartz.PostgreSql/
โ โโโ EasyCore.Quartz.Oracle/
โโโ demo/
โ โโโ WebApp.Quartz.InMemory/ # :5101 โ each demo owns SampleJob
โ โโโ WebApp.Quartz.MySql/ # :5102
โ โโโ WebApp.Quartz.SqlServer/ # :5103
โ โโโ WebApp.Quartz.PostgreSql/ # :5104
โ โโโ WebApp.Quartz.Oracle/ # :5105
โโโ tests/EasyCore.Quartz.Tests/
โโโ docs/svg/
2. Architecture
2.1 Component Diagram
2.2 Job Lifecycle
2.3 Data Flow
[EasyCoreCron Job]
โ
โผ
JobTypeDiscovery โโโบ JobWrapper<T> โโโบ Quartz Scheduler
โ โ
โ โผ
โ JobExecutionHistoryListener
โ โ
โโโโโโโโโ IJobManagementService โโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โผ โผ
Dashboard UI REST api/quartz
3. NuGet Packages
| Package | Role | Required |
|---|---|---|
EasyCore.Quartz |
Core, REST, History | โ |
EasyCore.Quartz.Dashboard |
English ops dashboard + Basic Auth | Optional |
EasyCore.Quartz.MySql |
MySQL store + schema bootstrap | Optional |
EasyCore.Quartz.SqlServer |
SQL Server store + schema bootstrap | Optional |
EasyCore.Quartz.PostgreSql |
PostgreSQL store + schema bootstrap | Optional |
EasyCore.Quartz.Oracle |
Oracle store + schema bootstrap | Optional |
4. Database Comparison
| Capability | In-Memory | MySQL | SQL Server | PostgreSQL | Oracle |
|---|---|---|---|---|---|
| Package | Core only | .MySql |
.SqlServer |
.PostgreSql |
.Oracle |
| Persistence | โ | โ | โ | โ | โ |
| Clustering | โ | โ | โ | โ | โ |
| AutoCreateSchema | โ | โ | โ | โ | โ |
| Table prefix | โ | QRTZ_ |
QRTZ_ |
QRTZ_ |
QRTZ_ |
| Typical use | Local trial | Common Linux stack | Enterprise Windows | Cloud / open source | Legacy enterprise |
4.1 Decision Tree
Need persistence / multi-node?
โโโ No โ In-Memory (WebApp.Quartz.InMemory)
โโโ Yes โ Pick your existing database
โโโ MySQL / MariaDB โ EasyCore.Quartz.MySql
โโโ SQL Server โ EasyCore.Quartz.SqlServer
โโโ PostgreSQL โ EasyCore.Quartz.PostgreSql
โโโ Oracle โ EasyCore.Quartz.Oracle
5. Requirements
| Item | Requirement |
|---|---|
| .NET | 8.0+ |
| Host | ASP.NET Core (Web / API) |
| Quartz.NET | 3.14 (brought by core package) |
| Database | Optional; required only for persistence |
6. Installation
dotnet add package EasyCore.Quartz
dotnet add package EasyCore.Quartz.Dashboard
# pick one as needed
dotnet add package EasyCore.Quartz.MySql
dotnet add package EasyCore.Quartz.SqlServer
dotnet add package EasyCore.Quartz.PostgreSql
dotnet add package EasyCore.Quartz.Oracle
7. Quick Start (3 minutes)
7๏ธโฃ.1๏ธโฃ Define a job
using EasyCore.Quartz;
using Quartz;
[EasyCoreCron("0/10 * * * * ?")]
[EasyCoreDisallowConcurrentExecution]
public sealed class SampleJob : IEasyCoreJob
{
private readonly ILogger<SampleJob> _logger;
public SampleJob(ILogger<SampleJob> logger) => _logger = logger;
public Task Execute(IJobExecutionContext context)
{
_logger.LogInformation("SampleJob running at {Time}", DateTimeOffset.Now);
return Task.CompletedTask;
}
}
Disable without deleting code:
[EasyCoreDisableJob]
[EasyCoreCron("0 0 * * * ?")]
public sealed class DisabledJob : IEasyCoreJob
{
public Task Execute(IJobExecutionContext context) => Task.CompletedTask;
}
7๏ธโฃ.2๏ธโฃ Register services (including dashboard)
// Reference EasyCore.Quartz.Dashboard
builder.Services.AddEasyCoreQuartz(options =>
{
options.AddAssemblyFrom<SampleJob>();
options.TimeZoneOffsetHours = +8;
options.AutoCreateSchema = true;
// RAM by default. For persistence, uncomment one:
// options.UseMySql(m => m.ConnectionString = "...");
// options.UseSqlServer(s => s.ConnectionString = "...");
// options.UsePostgreSql(p => p.ConnectionString = "...");
// options.UseOracle(o => o.ConnectionString = "...");
// Dashboard URL = app base URL + PathMatch
// No app.UseEasyCoreQuartzDashboard(...) needed
options.UseEasyCoreQuartzDashboard(dash =>
{
dash.PathMatch = "/easy-quartz";
dash.Username = "admin";
dash.Password = "admin123";
});
});
Open: http://localhost:<port>/easy-quartz/ (browser prompts for username/password)
8. Attributes & Options
| Attribute / Option | Description |
|---|---|
IEasyCoreJob |
Marker interface (extends Quartz IJob) |
[EasyCoreCron] |
Cron, JobKey, JobGroup, Misfire, RequestRecovery |
[EasyCoreDisableJob] |
Skip auto-registration |
[EasyCoreDisallowConcurrentExecution] |
Prevent overlapping runs |
AddAssembly / AddAssemblyFrom<T> |
Explicit discovery |
AutoCreateSchema |
Idempotent DDL on startup (disable in prod) |
HistoryCapacity |
In-memory history ring buffer size (default 200); Overview success/failure counts are window stats |
HttpJobTimeout |
HTTP job timeout (default 30s) |
HttpJobBlockPrivateNetworks |
Default true โ blocks loopback/private/metadata hosts |
HttpJobAllowedHosts |
HTTP job host allow-list (e.g. localhost) |
TablePrefix |
Default QRTZ_ (must match DDL) |
MaxConcurrency |
Thread pool size; 0 = auto |
9. Dashboard (English UI)
9.1 Preview
9.2 Pages
| Page | Icon | Capabilities |
|---|---|---|
| Overview | ๐ | Scheduler status, job/trigger counts, failure stats |
| Jobs | ๐ | List; Pause / Resume / Trigger / Delete / Edit Cron / Detail |
| Recurring | ๐ | Cron jobs only |
| Executing | โก | Currently running jobs |
| HTTP Jobs | ๐ | Create / update HTTP invoke jobs |
| History | ๐ | Recent executions (node-local memory) |
| Servers | ๐ฅ๏ธ | Scheduler name / InstanceId / Store |
โ ๏ธ History is a process-local ring buffer. Overview success/failure counts reflect the current window only (not lifetime totals) and are not shared across nodes.
9.3 Authorization (HTTP Basic Auth)
options.UseEasyCoreQuartzDashboard(dash =>
{
dash.PathMatch = "/easy-quartz"; // full URL = app base + this path
dash.Username = "admin"; // required
dash.Password = "admin123"; // required
});
| Option | Description |
|---|---|
PathMatch |
Relative path (default /easy-quartz) |
Username / Password |
Basic Auth credentials (required; middleware auto-mounted) |
BasicAuthAuthorizationFilter |
Enabled by default |
LocalRequestsOnlyAuthorizationFilter |
Optional; append to dash.Authorization |
Custom IEasyCoreQuartzAuthorizationFilter |
Replace or stack for production |
10. REST API
Base path: api/quartz
| Method | Path | Description |
|---|---|---|
| GET | /overview |
Overview |
| GET | /jobs |
All jobs |
| GET | /jobs/{group}/{name} |
Job detail |
| GET | /recurring |
Cron jobs |
| GET | /executing |
Executing jobs |
| GET | /history?take=100 |
History |
| PUT | /jobs/{group}/{name}/pause |
Pause |
| PUT | /jobs/{group}/{name}/resume |
Resume |
| PUT | /jobs/{group}/{name}/cron?cron=... |
Update cron |
| DELETE | /jobs/{group}/{name} |
Delete |
| POST | /jobs/{group}/{name}/trigger |
Trigger now |
| POST | /http-jobs |
Add/update HTTP job |
11. HTTP Jobs
Create via Dashboard HTTP Jobs or REST:
{
"jobName": "PingApi",
"jobGroup": "DEFAULT",
"url": "https://example.com/demo/ping",
"method": "GET",
"cron": "0/30 * * * * ?",
"headers": { "X-Trace": "demo" },
"body": "",
"description": "Health ping"
}
| Capability | Notes |
|---|---|
| Method | GET / POST / PUT / DELETE / PATCH (case-insensitive) |
| Body | JSON validated for POST/PUT/PATCH |
| Timeout | HttpJobTimeout (default 30s) |
| SSRF | Blocks loopback/private/link-local/metadata by default; allow via HttpJobAllowedHosts |
| Failure | Non-2xx โ exception โ History failure |
To call a local demo API, allow the host explicitly:
options.HttpJobAllowedHosts.Add("localhost");
options.HttpJobAllowedHosts.Add("127.0.0.1");
12. Database Configuration
All providers use table prefix QRTZ_.
๐ฌ MySQL
options.UseMySql(mysql =>
{
mysql.ConnectionString =
"server=localhost;port=3306;user id=root;password=***;database=EasyCoreQuartz;";
});
๐ฆ SQL Server
options.UseSqlServer(sql =>
{
sql.ConnectionString =
"Server=.;Database=EasyCoreQuartz;User Id=sa;Password=***;TrustServerCertificate=True;";
});
๐ PostgreSQL
options.UsePostgreSql(pg =>
{
pg.ConnectionString =
"Host=localhost;Port=5432;Database=EasyCoreQuartz;Username=postgres;Password=***";
});
๐ถ Oracle
options.UseOracle(ora =>
{
ora.ConnectionString =
"User Id=quartz;Password=***;Data Source=localhost:1521/ORCL";
});
Production DDL tip
options.AutoCreateSchema = false; // disable auto DDL in production
Apply official Quartz scripts (or freeze scripts generated in staging) through your migration pipeline.
13. Clustering & Concurrency
| Option | Default | Description |
|---|---|---|
CheckinInterval |
5s | Cluster check-in interval |
CheckinMisfireThreshold |
10s | Check-in misfire threshold |
MaxConcurrency |
20 | Thread pool; 0 = auto |
Configuring any persistent provider enables Quartz clustering.
Prevent overlapping execution:
[EasyCoreDisallowConcurrentExecution]
[EasyCoreCron("0/5 * * * * ?")]
public sealed class ExclusiveJob : IEasyCoreJob { /* ... */ }
14. Demo Projects
| Project | Store | Port | Command |
|---|---|---|---|
WebApp.Quartz.InMemory |
RAM | 5101 | dotnet run --project demo/WebApp.Quartz.InMemory |
WebApp.Quartz.MySql |
MySQL | 5102 | dotnet run --project demo/WebApp.Quartz.MySql |
WebApp.Quartz.SqlServer |
SQL Server | 5103 | dotnet run --project demo/WebApp.Quartz.SqlServer |
WebApp.Quartz.PostgreSql |
PostgreSQL | 5104 | dotnet run --project demo/WebApp.Quartz.PostgreSql |
WebApp.Quartz.Oracle |
Oracle | 5105 | dotnet run --project demo/WebApp.Quartz.Oracle |
Each demo has its own Jobs/SampleJob.cs โ open and edit locally, no cross-project reference.
dotnet run --project demo/WebApp.Quartz.InMemory
# open http://localhost:5101/easy-quartz
For DB demos, update ConnectionStrings:Quartz in the corresponding appsettings.json first.
15. Migrating from older versions
8.0.0 is a breaking release (relative to earlier Quarzt* naming):
| Older | 8.0 |
|---|---|
QuarztOptions |
EasyCoreQuartzOptions |
api/Quarzt |
api/quartz |
Typo Quarzt |
Corrected everywhere |
| Scan all BaseDirectory DLLs | EntryAssembly + AddAssembly |
| Swallowed job exceptions | Log and rethrow |
Prefix qrtz_ |
Unified QRTZ_ |
| Mixed licenses | MIT |
16. Production Checklist
- Use a strong dashboard password (never ship demo credentials publicly)
- Set
AutoCreateSchema = falsewith reviewed migrations - Keep connection strings in a secret store
- Monitor logs and History window failure counts (not lifetime totals)
- HTTP jobs: review
HttpJobAllowedHosts/ egress policy; do not casually disable private-network blocking - Set
MaxConcurrencyexplicitly under heavy load - Validate cron expressions before deploy
- Multi-node setups must share the same store and table prefix
17. FAQ
Q: Dashboard returns 401?
A: The browser prompts for Basic Auth. Use the configured Username / Password. Enabling the dashboard without credentials throws at startup.
Q: Does RAM mode include the dashboard?
A: Yes. Reference EasyCore.Quartz.Dashboard and call options.UseEasyCoreQuartzDashboard(...).
Q: Why is History different across nodes?
A: History is a process-local ring buffer; Overview success/failure counts cover the current window only. Use your logging/audit stack for cross-node history.
Q: HTTP job to localhost is rejected?
A: SSRF protection is on by default. Add the host to options.HttpJobAllowedHosts, or disable HttpJobBlockPrivateNetworks only in controlled environments.
Q: Does default Method=GET fail validation?
A: No. Validation is case-insensitive in 8.0.
Q: How do I scan only my business assembly?
A: options.AddAssemblyFrom<YourJob>() or options.AddAssembly(asm).
18. License
MIT โ see LICENSE.
๐ค Contributing
- Fork and create a feature branch
- Add tests under
tests/EasyCore.Quartz.Tests - Run
dotnet testanddotnet build EasyCore.Quartz.sln - Open a pull request
Issues and PRs are welcome ๐
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- EasyCore.Quartz (>= 8.3.0)
- Oracle.ManagedDataAccess.Core (>= 23.7.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.