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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EasyCore.Hangfire.Oracle" Version="8.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyCore.Hangfire.Oracle" Version="8.3.0" />
                    
Directory.Packages.props
<PackageReference Include="EasyCore.Hangfire.Oracle" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EasyCore.Hangfire.Oracle --version 8.3.0
                    
#r "nuget: EasyCore.Hangfire.Oracle, 8.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EasyCore.Hangfire.Oracle@8.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EasyCore.Hangfire.Oracle&version=8.3.0
                    
Install as a Cake Addin
#tool nuget:?package=EasyCore.Hangfire.Oracle&version=8.3.0
                    
Install as a Cake Tool

🔥 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.

.NET C# Hangfire DB License Version


🌍 Language


📚 Table of Contents


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

  1. Fork and create a feature branch
  2. Add tests under tests/EasyCore.Hangfire.Tests
  3. Run dotnet test and dotnet build EasyCore.Hangfire.sln
  4. Open a pull request

Issues and PRs are welcome 🚀

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.3.0 94 7/21/2026
8.0.0 86 7/18/2026