OrderSequenceGenerator 1.0.2
dotnet add package OrderSequenceGenerator --version 1.0.2
NuGet\Install-Package OrderSequenceGenerator -Version 1.0.2
<PackageReference Include="OrderSequenceGenerator" Version="1.0.2" />
<PackageVersion Include="OrderSequenceGenerator" Version="1.0.2" />
<PackageReference Include="OrderSequenceGenerator" />
paket add OrderSequenceGenerator --version 1.0.2
#r "nuget: OrderSequenceGenerator, 1.0.2"
#:package OrderSequenceGenerator@1.0.2
#addin nuget:?package=OrderSequenceGenerator&version=1.0.2
#tool nuget:?package=OrderSequenceGenerator&version=1.0.2
OrderSequenceGenerator
A high-performance, atomic order and sequence number generator for .NET 8 using PostgreSQL.
- Zero Manual SQL Setup: Automatically creates your database table, columns, and unique constraints when your application starts.
- 17 Ready-to-Use Patterns: Built-in support for e-Seba, retail, POS, tax invoices, and custom formats.
- 100% Concurrency Safe: Uses atomic database operations (
INSERT ... ON CONFLICT DO UPDATE) to guarantee zero duplicate numbers and zero gaps. - Interactive Setup Tool: Includes a PowerShell script (
walkthrough.ps1) that copies itself to your project to help you test patterns and database settings.
π Quick Start (3 Easy Steps)
Step 1: Install the Package
Run this command in your project folder:
dotnet add package OrderSequenceGenerator
Step 2: Build Your Project
Build your application to automatically copy the interactive setup tool into your project folder:
dotnet build
Note: Building your project places
walkthrough.ps1in your project root folder.
Step 3: Run the Setup Assistant (Optional)
Run the script to preview patterns and verify your database connection:
.\walkthrough.ps1
π οΈ How to Use in C#
1. Register the Service in Program.cs
Add the generator to your application services. You do not need to write any SQLβthe library creates the table and all required columns automatically.
using OrderSequenceGenerator;
using OrderSequenceGenerator.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOrderSequenceGenerator(options =>
{
// Provide your PostgreSQL connection string
options.ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection")!;
// Choose a pattern (preset or custom)
options.Pattern = OrderPatterns.ESebaCompact; // Format: {DISTRICT}{yyyy}{PREFIX}{MM}{dd}{SEQ:4}
// Automatically create table and columns on startup
options.AutoMigrate = true;
// Optional: customize the table name (default is "order_sequence")
options.TableName = "order_sequence";
});
var app = builder.Build();
app.Run();
2. Generate Numbers in Your Controllers or Services
Inject IOrderSequenceGenerator and call NextAsync. Date values (yyyy, MM, dd) are filled in automatically using the current UTC time.
ASP.NET Core Controller Example:
using Microsoft.AspNetCore.Mvc;
using OrderSequenceGenerator;
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderSequenceGenerator _generator;
public OrdersController(IOrderSequenceGenerator generator)
{
_generator = generator;
}
[HttpPost]
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
{
// Pass your custom token values as an object:
string orderNumber = await _generator.NextAsync(new
{
District = request.District, // Example: "MN051"
Prefix = "E"
});
// Returns: "MN05120260909E0001"
return Ok(new { OrderNumber = orderNumber });
}
}
Minimal API Example:
app.MapPost("/api/orders", async (IOrderSequenceGenerator generator) =>
{
string orderNumber = await generator.NextAsync(new { Prefix = "ORD" });
return Results.Ok(new { OrderNumber = orderNumber }); // Example: "ORD-20260909-0001"
});
Using a Dictionary:
var tokens = new Dictionary<string, string>
{
{ "DISTRICT", "MN051" },
{ "PREFIX", "E" }
};
string orderNumber = await _generator.NextAsync(tokens);
Getting Only the Numeric Value:
long sequenceNumber = await _generator.NextRawSequenceAsync(new { District = "MN051", Prefix = "E" });
// Returns: 1, 2, 3, etc.
π§© Built-in Pattern Presets
You can use any of the 17 built-in patterns from OrderPatterns:
| Pattern Constant | Format Template | Example Output | Reset Frequency |
|---|---|---|---|
OrderPatterns.ESebaCompact |
{DISTRICT}{yyyy}{PREFIX}{MM}{dd}{SEQ:4} |
MN0512026E09090001 |
Daily per District & Prefix |
OrderPatterns.ESebaDelimited |
{DISTRICT}-{yyyy}{MM}{dd}-{PREFIX}-{SEQ:4} |
MN051-20260909-E-0001 |
Daily per District & Prefix |
OrderPatterns.DeptCitizenService |
{DEPT}-{DISTRICT}-{yyyy}-{SEQ:4} |
REV-MN051-2026-0001 |
Yearly per Dept & District |
OrderPatterns.StandardRetail |
{PREFIX}-{yyyyMMdd}-{SEQ:4} |
ORD-20260909-0001 |
Daily per Prefix |
OrderPatterns.StoreCounterPos |
{PREFIX}-{STORE}-{POS}-{yyMM}-{SEQ:3} |
ORD-NY01-C1-2609-001 |
Monthly per Store & POS |
OrderPatterns.MultiBranchRetail |
{PREFIX}-{BRANCH}-{yyyyMMdd}-{SEQ:4} |
ORD-MUM-20260909-0001 |
Daily per Branch |
OrderPatterns.MonthlyInvoice |
{PREFIX}/{yyyy}/{MM}/{SEQ:4} |
INV/2026/09/0001 |
Monthly per Prefix |
OrderPatterns.FiscalYearInvoice |
{PREFIX}/{yy}-{next_yy}/{SEQ:6} |
INV/26-27/000001 |
Yearly (Fiscal Year) |
OrderPatterns.PurchaseOrder |
{PREFIX}-{yyyy}-{SEQ:5} |
PO-2026-00012 |
Yearly per Prefix |
OrderPatterns.ShipmentWaybill |
{PREFIX}{yyyyMMdd}{SEQ:5} |
SHP2026090900001 |
Daily per Prefix |
OrderPatterns.HealthcareToken |
{PREFIX}-{DEPT}-{yyMMdd}-{SEQ:3} |
TKN-CARD-260909-001 |
Daily per Department |
OrderPatterns.BankingTxn |
{PREFIX}-{yyyyMMdd}-{SEQ:6} |
TXN-20260909-000001 |
Daily per Prefix |
OrderPatterns.LoanApplication |
{PREFIX}-{TYPE}-{yyyy}-{SEQ:4} |
LN-HL-2026-0001 |
Yearly per Loan Type |
OrderPatterns.PaymentReceipt |
{PREFIX}/{yyyy}/{MM}/{SEQ:4} |
REC/2026/09/0001 |
Monthly per Prefix |
OrderPatterns.SupportTicket |
{PREFIX}-{yyyy}-{SEQ:5} |
TKT-2026-00001 |
Yearly per Prefix |
OrderPatterns.ContinuousAccount |
{PREFIX}-{SEQ:6} |
ACC-000042 |
Never (Continuous) |
π¨ Creating Custom Patterns
You can define any pattern format using standard tokens:
options.Pattern = "{COMPANY}-{BRANCH}-{yyyyMMdd}-{SEQ:5}";
- Date Tokens:
{yyyy}(4-digit year),{yy}(2-digit year),{MM}(2-digit month),{dd}(2-digit day),{yyyyMMdd},{yyMMdd}. - Sequence Token:
{SEQ:N}whereNis the number of digits to pad (e.g.{SEQ:4}gives0001). - Custom Tokens: Any word like
{COMPANY},{BRANCH}, or{DEPT}. The library creates matching database columns automatically.
π§ͺ Testing in Unit Tests (Without a Database)
To run unit tests or develop offline without PostgreSQL, use the in-memory store:
services.AddInMemoryOrderSequenceGenerator(options =>
{
options.Pattern = OrderPatterns.StandardRetail;
});
ποΈ How Database Storage Works
When AutoMigrate = true is enabled, the library automatically creates the table structure in PostgreSQL:
id: Primary key (BIGSERIAL PRIMARY KEY).- Scope Columns: Created automatically for each token in your pattern (for example:
district,prefix,year,month,day). sequence: Current counter value (BIGINT NOT NULL DEFAULT 0).updated_at: Last updated timestamp (TIMESTAMP WITH TIME ZONE).- Unique Constraint: A composite unique constraint ensures each combination of scope values maintains its own independent sequence.
Concurrency Safety
All numbers are generated using an atomic query:
INSERT INTO order_sequence (district, prefix, year, month, day, sequence, updated_at)
VALUES (@district, @prefix, @year, @month, @day, 1, CURRENT_TIMESTAMP)
ON CONFLICT (district, prefix, year, month, day)
DO UPDATE SET sequence = order_sequence.sequence + 1, updated_at = CURRENT_TIMESTAMP
RETURNING sequence;
This guarantees zero duplicate numbers and zero gaps, even under heavy concurrent load across multiple servers.
π License
This project is licensed under the MIT License.
| 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
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
- Npgsql (>= 8.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version 1.0.2: Clarified quick start instructions to run 'dotnet build' after adding the package so 'walkthrough.ps1' is placed in project root immediately.