EasyCore.Hangfire.Oracle
8.3.0
dotnet add package EasyCore.Hangfire.Oracle --version 8.3.0
NuGet\Install-Package EasyCore.Hangfire.Oracle -Version 8.3.0
<PackageReference Include="EasyCore.Hangfire.Oracle" Version="8.3.0" />
<PackageVersion Include="EasyCore.Hangfire.Oracle" Version="8.3.0" />
<PackageReference Include="EasyCore.Hangfire.Oracle" />
paket add EasyCore.Hangfire.Oracle --version 8.3.0
#r "nuget: EasyCore.Hangfire.Oracle, 8.3.0"
#:package EasyCore.Hangfire.Oracle@8.3.0
#addin nuget:?package=EasyCore.Hangfire.Oracle&version=8.3.0
#tool nuget:?package=EasyCore.Hangfire.Oracle&version=8.3.0
🔥 EasyCore.Hangfire
EasyCore.Hangfire is a Hangfire wrapper for .NET 8. It provides attribute-based recurring jobs, Hangfire Dashboard, REST management APIs, dynamic HTTP jobs, and persistence for MySQL / SQL Server / PostgreSQL / Oracle.
🌍 Language
- Chinese: README.md
- English (this document)
📚 Table of Contents
- 1. Positioning
- 2. NuGet Packages
- 3. Database Selection
- 4. Installation
- 5. Quick Start
- 6. Attributes & Options
- 7. Dashboard
- 8. REST API
- 9. Database Configuration
- 10. Demo Projects
- 11. FAQ
- 12. License
1. Positioning
| Pain point | EasyCore.Hangfire approach |
|---|---|
| Manual RecurringJob wiring | IEasyCoreHangfireJob + [EasyCoreRecurring] auto-discovery |
| Missing ops UI | Built-in Hangfire Dashboard (/hangfire) |
| Split management APIs | Unified api/Hangfire REST |
| Multi-DB persistence | Separate MySQL / SQL Server / PostgreSQL / Oracle packages |
| Swallowed exceptions | JobWrapper logs and rethrows |
| Missing history / disallow concurrent | In-process History ring buffer + [EasyCoreDisallowConcurrentExecution] |
Repository layout
EasyCore.Hangfire/
├── src/
│ ├── EasyCore.Hangfire/ # Core: discovery, dashboard, REST, HTTP jobs
│ ├── EasyCore.Hangfire.MySql/
│ ├── EasyCore.Hangfire.SqlServer/
│ ├── EasyCore.Hangfire.PostgreSql/
│ └── EasyCore.Hangfire.Oracle/
├── demo/
│ ├── WebApp.Hangfire/ # MySQL / SQL Server sample
│ ├── WebApp.Hangfire.PostgreSql/
│ └── WebApp.Hangfire.Oracle/
├── tests/EasyCore.Hangfire.Tests/
└── png/EasyCoreLogo.png
2. NuGet Packages
| Package | Role | Required |
|---|---|---|
EasyCore.Hangfire |
Core, Dashboard, REST, memory storage | ✅ |
EasyCore.Hangfire.MySql |
MySQL persistence | Optional |
EasyCore.Hangfire.SqlServer |
SQL Server persistence | Optional |
EasyCore.Hangfire.PostgreSql |
PostgreSQL persistence | Optional |
EasyCore.Hangfire.Oracle |
Oracle persistence | Optional |
When no database provider is configured, the core package defaults to MemoryStorage.
3. Database Selection
| Capability | Memory | MySQL | SQL Server | PostgreSQL | Oracle |
|---|---|---|---|---|---|
| Package | Core only | .MySql |
.SqlServer |
.PostgreSql |
.Oracle |
| Persistence | ❌ | ✅ | ✅ | ✅ | ✅ |
| Multi-node share | ❌ | ✅ | ✅ | ✅ | ✅ |
| Typical use | Local trial | Common Linux stack | Enterprise Windows | Cloud native | Legacy enterprise |
Need persistence / multi-node?
├── No → MemoryStorage (do not call Use*)
└── Yes → Pick your existing database
├── MySQL → EasyCore.Hangfire.MySql
├── SQL Server → EasyCore.Hangfire.SqlServer
├── PostgreSQL → EasyCore.Hangfire.PostgreSql
└── Oracle → EasyCore.Hangfire.Oracle
4. Installation
dotnet add package EasyCore.Hangfire
# pick one as needed
dotnet add package EasyCore.Hangfire.MySql
dotnet add package EasyCore.Hangfire.SqlServer
dotnet add package EasyCore.Hangfire.PostgreSql
dotnet add package EasyCore.Hangfire.Oracle
5. Quick Start
5.1 Define a job
using EasyCore.Hangfire;
[EasyCoreRecurring("*/1 * * * *")] // 5-field cron; minimum unit = minute
[EasyCoreDisallowConcurrentExecution] // prevent overlapping runs (distributed lock)
public sealed class SampleJob : IEasyCoreHangfireJob
{
private readonly ILogger<SampleJob> _logger;
public SampleJob(ILogger<SampleJob> logger) => _logger = logger;
public Task ExecuteAsync(CancellationToken cancellationToken = default)
{
_logger.LogInformation("SampleJob running at {Time}", DateTimeOffset.Now);
return Task.CompletedTask;
}
}
Disable without deleting code:
[EasyCoreDisableJob]
[EasyCoreRecurring("0 * * * *")]
public sealed class DisabledJob : IEasyCoreHangfireJob
{
public Task ExecuteAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
}
5.2 Register services
builder.Services.AddEasyCoreHangfire(options =>
{
options.TimeZoneOffsetHours = +8;
// Or an explicit system time zone (recommended in production):
// options.TimeZoneId = "China Standard Time"; // Linux: Asia/Shanghai
// Management auth (shared by Dashboard + REST)
options.Username = "admin";
options.Password = "admin123";
options.EnableDashboard = true; // default false; credentials required when enabled
options.RequireApiBasicAuth = true; // default true
// HTTP jobs: allow local hosts in demos
options.HttpJobAllowedHosts.Add("localhost");
options.HttpJobAllowedHosts.Add("127.0.0.1");
options.UseMySql(mysql =>
{
mysql.ConnectionString =
"server=localhost;port=3306;user id=root;password=***;database=EasyCoreHangfire;";
// Automatically appends Allow User Variables=true (required by Hangfire.MySqlStorage)
});
// options.UseSqlServer(s => s.ConnectionString = "...");
// options.UsePostgreSql(p => p.ConnectionString = "...");
// options.UseOracle(o => o.ConnectionString = "...");
});
var app = builder.Build();
app.UseEasyCoreHangfire();
app.MapControllers();
6. Attributes & Options
| Attribute / Option | Description |
|---|---|
IEasyCoreHangfireJob |
Marker interface |
[EasyCoreRecurring] |
Cron, optional JobId / Queue |
[EasyCoreDisableJob] |
Skip auto-registration |
[EasyCoreDisallowConcurrentExecution] |
Prevent overlapping runs (Hangfire distributed lock; multi-node aware) |
HistoryCapacity |
In-memory history ring buffer size (default 200); Overview success/failure counts are window stats |
HttpJobDisallowConcurrent |
Prevent overlapping HTTP jobs with the same name (default true) |
HttpJobConcurrentLockTimeoutSeconds |
Lock wait seconds for HTTP jobs (default 0 = do not wait) |
TimeZoneOffsetHours |
Display/schedule offset (resolved to a system zone) |
TimeZoneId |
Explicit system time zone id (wins over offset) |
WorkerCount |
Hangfire worker count (default 20) |
EnableDashboard |
Enable dashboard (default false) |
DashboardPath |
Dashboard path (default /hangfire) |
Username / Password |
Basic Auth for Dashboard + REST |
RequireApiBasicAuth |
Require Basic Auth for REST (default true) |
HttpJobTimeout |
HTTP job timeout (default 30s) |
HttpJobBlockPrivateNetworks |
Blocks loopback/private/metadata by default |
HttpJobAllowedHosts |
HTTP job host allow-list |
HttpJobStorePath |
Persisted HTTP job definitions file |
⚠️ Hangfire cron does not support seconds.
*/1 * * * *means every minute, not every second.
7. Dashboard
options.EnableDashboard = true;
options.DashboardPath = "/hangfire";
options.Username = "admin";
options.Password = "admin123";
Open: http://localhost:<port>/hangfire (browser prompts for Basic Auth).
Enabling the dashboard without credentials throws at startup.
8. REST API
Base path: api/Hangfire (Basic Auth required by default)
| Method | Path | Description |
|---|---|---|
| GET | /overview |
Overview (recurring job count + History window success/failure) |
| GET | /history?take=100 |
Recent execution history (process-local ring buffer) |
| GET | /get/all/jobs |
All recurring job statuses |
| PUT | /pause/job?jobName= |
Pause |
| PUT | /resume/job?jobName= |
Resume |
| PUT | /update/cron?jobName=&newCron= |
Update cron |
| POST | /manualtrigger/job?jobName= |
Trigger now |
| POST | /addorupdate/httpjob |
Add/update HTTP job |
Disable REST auth only in controlled environments:
options.RequireApiBasicAuth = false;
9. HTTP Jobs
Create via REST POST /api/Hangfire/addorupdate/httpjob:
{
"jobName": "PingApi",
"url": "https://example.com/demo/ping",
"method": "GET",
"cron": "*/5 * * * *",
"headers": { "X-Trace": "demo" },
"body": "",
"queue": "default"
}
| Capability | Notes |
|---|---|
| URL validation | http/https only; blocks loopback/private/metadata by default (SSRF) |
| Timeout | HttpJobTimeout (default 30s) |
| Failure | Non-2xx ⇒ exception ⇒ Hangfire failure |
| Disallow concurrent | Distributed lock per JobName by default (HttpJobDisallowConcurrent) |
| History | Success/failure recorded into the process-local History store |
| Persistence | Definitions saved to HttpJobStorePath; restored on startup |
To call a local demo API:
options.HttpJobAllowedHosts.Add("localhost");
options.HttpJobAllowedHosts.Add("127.0.0.1");
10. Database Configuration
🐬 MySQL
options.UseMySql(mysql =>
{
mysql.ConnectionString =
"server=localhost;port=3306;user id=root;password=***;database=EasyCoreHangfire;";
});
🟦 SQL Server
options.UseSqlServer(sql =>
{
sql.ConnectionString =
"Server=.;Database=EasyCoreHangfire;User Id=sa;Password=***;TrustServerCertificate=True;";
});
🐘 PostgreSQL
options.UsePostgreSql(pg =>
{
pg.ConnectionString =
"Host=localhost;Port=5432;Database=EasyCoreHangfire;Username=postgres;Password=***";
pg.SchemaName = "hangfire";
});
🔶 Oracle
options.UseOracle(ora =>
{
ora.ConnectionString =
"User Id=hangfire;Password=***;Data Source=localhost:1521/ORCL";
ora.SchemaName = "HANGFIRE";
});
Legacy aliases still work: EasyCoreHangfireMySql / EasyCoreHangfireSqlServer / EasyCoreHangfirePostgreSql / EasyCoreHangfireOracle.
11. Demo Projects
| Project | Store | Command |
|---|---|---|
WebApp.Hangfire |
Memory / MySQL / SQL Server (switchable) | dotnet run --project demo/WebApp.Hangfire |
WebApp.Hangfire.PostgreSql |
PostgreSQL | dotnet run --project demo/WebApp.Hangfire.PostgreSql |
WebApp.Hangfire.Oracle |
Oracle | dotnet run --project demo/WebApp.Hangfire.Oracle |
Demo credentials: admin / admin123. Update connection strings / appsettings.json before running DB demos.
dotnet test tests/EasyCore.Hangfire.Tests
dotnet run --project demo/WebApp.Hangfire
# Dashboard: http://localhost:5024/hangfire (admin / admin123)
12. FAQ
Q: Dashboard returns 401?
A: Use the configured Username / Password. Credentials are required when EnableDashboard=true.
Q: REST returns 401?
A: RequireApiBasicAuth is on by default. Send Basic Auth, or disable only in controlled environments.
Q: Jobs are not running?
A: Check [EasyCoreDisableJob], verify storage connectivity, and inspect Recurring Jobs on /hangfire.
Q: TimeZoneNotFoundException?
A: Use a real system time zone id (China Standard Time / Asia/Shanghai). Prefer TimeZoneId over custom names.
Q: MySQL user-variable errors?
A: UseMySql appends Allow User Variables=true automatically. Include it if you build the connection string yourself.
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: Do HTTP jobs survive restart?
A: Yes. Definitions are persisted to HttpJobStorePath and restored on startup; Hangfire storage also keeps the recurring schedule.
Q: Need second-level scheduling?
A: Hangfire cron has no seconds field. Use EasyCore.Quartz, or a custom BackgroundService loop.
Q: Are History / Overview success counts cross-node?
A: No. 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. Multi-node [EasyCoreDisallowConcurrentExecution] requires shared Hangfire DB storage for distributed locks.
13. License
MIT
🤝 Contributing
- Fork and create a feature branch
- Add tests under
tests/EasyCore.Hangfire.Tests - Run
dotnet testanddotnet build EasyCore.Hangfire.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.Hangfire (>= 8.3.0)
- Hangfire.Core (>= 1.8.21)
- TH.Hangfire.Oracle (>= 1.8.21.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.