OrderSequenceGenerator 1.0.2

dotnet add package OrderSequenceGenerator --version 1.0.2
                    
NuGet\Install-Package OrderSequenceGenerator -Version 1.0.2
                    
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="OrderSequenceGenerator" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OrderSequenceGenerator" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="OrderSequenceGenerator" />
                    
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 OrderSequenceGenerator --version 1.0.2
                    
#r "nuget: OrderSequenceGenerator, 1.0.2"
                    
#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 OrderSequenceGenerator@1.0.2
                    
#: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=OrderSequenceGenerator&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=OrderSequenceGenerator&version=1.0.2
                    
Install as a Cake Tool

OrderSequenceGenerator

A high-performance, atomic order and sequence number generator for .NET 8 using PostgreSQL.

NuGet Version License: MIT

  • 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.ps1 in 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} where N is the number of digits to pad (e.g. {SEQ:4} gives 0001).
  • 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:

  1. id: Primary key (BIGSERIAL PRIMARY KEY).
  2. Scope Columns: Created automatically for each token in your pattern (for example: district, prefix, year, month, day).
  3. sequence: Current counter value (BIGINT NOT NULL DEFAULT 0).
  4. updated_at: Last updated timestamp (TIMESTAMP WITH TIME ZONE).
  5. 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 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
1.0.2 114 9/9/2026
1.0.1 101 9/9/2026
1.0.0 98 9/9/2026

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.