Core Concepts
NBatch is built around a small set of composable primitives. Understanding these concepts will help you design reliable batch jobs.
Packages
NBatch is distributed as two NuGet packages:
| Package | What’s inside |
|---|---|
NBatch | Core framework — job builder, step pipeline, readers, writers, skip policies, DI integration, hosted service |
NBatch.EntityFrameworkCore | EF Core job store for restart-from-failure — SQL Server, PostgreSQL, SQLite, MySQL |
Install the core package to get started. Add the EF Core package only if you need persistent job tracking:
dotnet add package NBatch
dotnet add package NBatch.EntityFrameworkCore # optional
Job
A Job is a named container of one or more steps, executed in order. You create jobs using the fluent builder API:
var job = Job.CreateBuilder("my-job")
.AddStep("step-1", step => step
.ReadFrom(reader)
.WriteTo(writer))
.AddStep("step-2", step => step
.ReadFrom(reader2)
.WriteTo(writer2))
.Build();
await job.RunAsync();
A Job returns a JobResult containing the aggregate success status and per-step details.
Step (Chunk-Oriented)
A Step is a chunk-oriented pipeline that follows the Reader > Processor > Writer pattern:
+------------+ +--------------+ +------------+
| Reader |---->| Processor |---->| Writer |
| IReader<T> | | IProcessor | | IWriter<T> |
+------------+ +--------------+ +------------+
Each iteration:
- The Reader reads a chunk of items (controlled by
ChunkSize, default10). - The Processor transforms each item (optional – if omitted, items pass through unchanged).
- The Writer persists the processed chunk to a destination.
This loop repeats until the reader returns no more data.
.AddStep("import", step => step
.ReadFrom(new CsvReader<Product>(filePath, mapFn))
.ProcessWith(p => new ProductDto(p.Name, p.Price * 1.1m))
.WriteTo(new DbWriter<ProductDto>(dbContext))
.WithChunkSize(100))
Chunk Size
The chunk size controls how many items are read per iteration. Larger chunks mean fewer database round-trips but more memory usage.
.WithChunkSize(500) // read 500 items per iteration
Default: 10
Tasklet Step
A Tasklet is a single unit of work that doesn’t follow the reader/writer pattern. Use it for fire-and-forget tasks like sending emails, calling APIs, or running stored procedures.
.AddStep("notify", step => step
.Execute(() => SendNotificationAsync()))
Tasklets support four signatures:
// Simple async action
.Execute(() => DoWorkAsync())
// With cancellation token
.Execute(async ct => await DoWorkAsync(ct))
// Synchronous action
.Execute(() => CleanUpTempFiles())
// Implement ITasklet for full control
.Execute(new MyTasklet())
The ITasklet interface:
public interface ITasklet
{
Task ExecuteAsync(CancellationToken cancellationToken = default);
}
The Pipeline Model
A multi-step job executes its steps sequentially. Each step is independent — a chunk-oriented step can be followed by a tasklet, or vice versa:
var job = Job.CreateBuilder("ETL")
.AddStep("extract", step => step
.ReadFrom(csvReader)
.ProcessWith(transformer)
.WriteTo(dbWriter)
.WithChunkSize(100))
.AddStep("validate", step => step
.Execute(() => RunValidationAsync()))
.AddStep("notify", step => step
.Execute(() => SendReportEmailAsync()))
.Build();
Dependency Injection
NBatch integrates with IServiceCollection for DI-based applications. Register jobs with AddNBatch() and run them on-demand via IJobRunner or automatically via background workers.
builder.Services.AddNBatch(nbatch =>
{
nbatch.AddJob("csv-import", (sp, job) => job
.AddStep("import", step => step
.ReadFrom(new CsvReader<Product>("data.csv", mapFn))
.WriteTo(new DbWriter<Product>(sp.GetRequiredService<AppDbContext>()))
.WithChunkSize(100)))
.RunEvery(TimeSpan.FromHours(1));
});
See DI & Hosted Service for the full guide.
Result Types
JobResult
Returned by job.RunAsync():
| Property | Type | Description |
|---|---|---|
Name | string | The job name |
Success | bool | true if all steps succeeded |
Steps | IReadOnlyList<StepResult> | Per-step results |
StepResult
| Property | Type | Description |
|---|---|---|
Name | string | The step name |
Success | bool | Whether the step completed successfully |
ItemsRead | int | Total items read by the reader |
ItemsProcessed | int | Total items written successfully |
ErrorsSkipped | int | Items skipped via the skip policy |
Next: Readers & Writers →