Bytesystems.NumberSequenceGenerator 1.2.0

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

Bytesystems.NumberSequenceGenerator

Attribute-driven number sequence generator for Entity Framework Core. Automatically generates sequential, formatted numbers for entity properties on SaveChanges.

Supports configurable patterns with date tokens, zero-padding, auto-reset (yearly/monthly/daily), and segmentation. .NET port of the ByteSystems Symfony NumberSequenceGeneratorBundle.

Installation

dotnet add package Bytesystems.NumberSequenceGenerator

Quick Start

1. Register services

builder.Services.AddNumberSequenceGenerator();

builder.Services.AddDbContext<AppDbContext>((sp, options) =>
{
    options.UseNpgsql(connectionString)
        .AddInterceptors(sp.GetRequiredService<NumberSequenceInterceptor>());
});

2. Configure the entity table

// In your DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new NumberSequenceEntityConfiguration());
}

3. Annotate your entities

public class Invoice
{
    public int Id { get; set; }

    [Sequence(Key = "invoice", Pattern = "IV{Y}-{#|6|y}")]
    public string? InvoiceNumber { get; set; }
}

4. Numbers are generated automatically

var invoice = new Invoice();
context.Invoices.Add(invoice);
await context.SaveChangesAsync();

Console.WriteLine(invoice.InvoiceNumber); // "IV2026-000001"

Pattern Syntax

Patterns use {token|param1|param2} syntax:

Token Description Example Output
{#} Sequence number (plain) 42
{#\|6} Sequence, zero-padded to 6 digits 000042
{#\|6\|y} Sequence, 6 digits, resets yearly 000001 (after Jan 1)
{Y} Year, 4 digits 2026
{y} Year, 2 digits 26
{m} Month, 2 digits 02
{M} Month, 3-letter abbreviation Feb
{d} Day, 2 digits 09
{D} Day, 3-letter abbreviation Mon
{w} ISO week number 06
{H} Hour, 24-hour format 14

Reset Contexts

The sequence token {#|padding|context} supports automatic counter reset:

Context Resets When
y Year changes
m Month changes
w ISO week changes
d Day changes
h Hour changes

Pattern Examples

"KD-{#|6}"              → KD-000142         (customer number, never resets)
"IV{Y}-{#|6|y}"         → IV2026-000023     (invoice, resets yearly)
"AG-{y}{m}-{#|4|m}"     → AG-2602-0015      (offer, resets monthly)
"JN-{y}{m}{d}-{#|5|d}"  → JN-260209-00003   (journal, resets daily)
"PO-{#|7}"              → PO-0001234        (order, never resets)

Segmentation

Different patterns for different entity types using the same sequence key:

// Define segments
[Segment(Value = "OFFER", Pattern = "AG-{y}{m}-{#|4|y}")]
public class OfferSegment;

[Segment(Value = "ORDER", Pattern = "KV-{y}{m}-{#|4|y}")]
public class OrderSegment;

// Use on entity
public class Document
{
    public string DocumentType { get; set; } = string.Empty;

    [Sequence(Key = "document", Segment = "{DocumentType}",
        Pattern = "DOC-{#|4}",
        Segments = new[] { typeof(OfferSegment), typeof(OrderSegment) })]
    public string? DocumentNumber { get; set; }
}

Each segment maintains its own independent counter.

Custom Token Handlers

Extend the system with custom tokens:

public class FiscalYearTokenHandler : ITokenHandler
{
    public bool Handles(Token token) => token.Identifier == "FY";
    public string GetValue(Token token, int sequenceValue)
    {
        var now = DateTime.UtcNow;
        var fiscalYear = now.Month >= 4 ? now.Year : now.Year - 1;
        return fiscalYear.ToString();
    }
    public bool RequestsReset(Token token) => false;
}

// Register
builder.Services.AddNumberSequenceGenerator(options =>
{
    options.AddTokenHandler<FiscalYearTokenHandler>();
});

// Use: "INV-{FY}-{#|5|y}" → "INV-2025-00042"

How It Works

  1. An EF Core SaveChangesInterceptor detects newly added entities
  2. It scans for properties with [Sequence] attributes via reflection
  3. The NumberGenerator service resolves the correct sequence from the database
  4. Tokens are parsed, reset logic is evaluated, the counter is incremented
  5. The formatted number is set on the property before the entity is saved
  6. The sequence counter is persisted in the number_sequences table

Configuration

Table Name

modelBuilder.ApplyConfiguration(new NumberSequenceEntityConfiguration("my_custom_table"));

Concurrency

The CurrentNumber column uses EF Core's [ConcurrencyCheck] for optimistic concurrency control. If two requests try to generate a number simultaneously, one will get a DbUpdateConcurrencyException and should retry.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.2.0 112 2/10/2026
1.1.0 91 2/9/2026
1.0.0 87 2/9/2026