Dtde.Abstractions 1.0.0

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

<div align="center">

DTDE - Distributed Temporal Data Engine

Transparent horizontal sharding and temporal versioning for Entity Framework Core

.NET EF Core License Tests GitHub

πŸ“š Documentation Β· πŸš€ Quick Start Β· πŸ’‘ Samples Β· πŸ“Š Benchmarks

</div>


Overview

DTDE is a NuGet package that adds transparent horizontal sharding and optional temporal versioning to Entity Framework Core applications. Write standard LINQ queries β€” DTDE handles data distribution, query routing, and result merging automatically.

// Standard EF Core LINQ - DTDE routes queries transparently
var euCustomers = await db.Customers
    .Where(c => c.Region == "EU")
    .ToListAsync();  // Automatically queries only EU shard

// Point-in-time queries for temporal entities
var ordersLastMonth = await db.ValidAt<Order>(DateTime.Today.AddMonths(-1))
    .Where(o => o.Status == "Completed")
    .ToListAsync();

✨ Key Features

Feature Description
πŸ”€ Transparent Sharding Distribute data across tables or databases invisibly
⏱️ Temporal Versioning Track entity history with point-in-time queries
🎯 Property Agnostic Use ANY property names for sharding keys and temporal boundaries
πŸ“ EF Core Native Works with standard LINQ β€” no special query syntax required
⚑ Multiple Strategies Date-based, hash-based, range-based, or composite sharding
πŸ—„οΈ Hot/Warm/Cold Tiers Support for data tiering across storage tiers
βœ… Fully Tested 100+ unit and integration tests

πŸ“¦ Installation

# All-in-one package (recommended)
dotnet add package Dtde.EntityFramework

# Or install individual packages
dotnet add package Dtde.Abstractions  # Core interfaces
dotnet add package Dtde.Core          # Core implementations
dotnet add package Dtde.EntityFramework  # EF Core integration

Requirements: .NET 8.0+ / 9.0+ / 10.0+, Entity Framework Core 8.0+ / 9.0+ / 10.0+


πŸš€ Quick Start

1. Define Your Entity

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Region { get; set; } = string.Empty;  // Shard key
    public DateTime CreatedAt { get; set; }
}

2. Create Your DbContext

public class AppDbContext : DtdeDbContext
{
    public DbSet<Customer> Customers => Set<Customer>();

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Customer>(entity =>
        {
            entity.ShardBy(c => c.Region);  // Enable sharding by Region
        });
    }
}

3. Configure Services

builder.Services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(connectionString);
    options.UseDtde(dtde =>
    {
        dtde.AddShard(s => s.WithId("EU").WithShardKeyValue("EU").WithTier(ShardTier.Hot));
        dtde.AddShard(s => s.WithId("US").WithShardKeyValue("US").WithTier(ShardTier.Hot));
        dtde.AddShard(s => s.WithId("APAC").WithShardKeyValue("APAC").WithTier(ShardTier.Hot));
    });
});

4. Use It!

// Queries are automatically routed to correct shard(s)
var allCustomers = await _context.Customers.ToListAsync();  // Queries all shards
var euCustomers = await _context.Customers
    .Where(c => c.Region == "EU")
    .ToListAsync();  // Only queries EU shard

// Inserts are automatically routed based on shard key
_context.Customers.Add(new Customer { Name = "Acme Corp", Region = "US" });  // Routes to US shard
await _context.SaveChangesAsync();

πŸ”€ Sharding Strategies

DTDE supports multiple sharding strategies to match your data access patterns:

Property-Based Sharding

Distribute data by a property value (region, tenant, category):

modelBuilder.Entity<Customer>(entity =>
{
    entity.ShardBy(c => c.Region);
});

Use cases: Multi-region deployments, GDPR compliance, data residency

Date-Based Sharding

Partition data by date for time-series workloads:

modelBuilder.Entity<Transaction>(entity =>
{
    entity.ShardByDate(t => t.TransactionDate, DateInterval.Month);
});

Use cases: Financial transactions, audit logs, metrics, event sourcing

Hash-Based Sharding

Even distribution across shards using consistent hashing:

modelBuilder.Entity<UserProfile>(entity =>
{
    entity.ShardByHash(u => u.UserId, shardCount: 8);
});

Use cases: High-volume data, preventing hotspots, horizontal scaling

Composite Sharding

Combine strategies for complex scenarios:

modelBuilder.Entity<Order>(entity =>
{
    entity.ShardBy(o => o.Region)
          .ThenByDate(o => o.OrderDate);
});

⏱️ Temporal Versioning

Track entity history and query data at any point in time:

Enable Temporal Tracking

modelBuilder.Entity<Contract>(entity =>
{
    entity.HasTemporalValidity(
        validFrom: nameof(Contract.ValidFrom),
        validTo: nameof(Contract.ValidTo));
});

Temporal Queries

// Current data
var current = await _context.ValidAt<Contract>(DateTime.UtcNow).ToListAsync();

// Historical data (as of a specific date)
var historical = await _context.ValidAt<Contract>(new DateTime(2024, 1, 1)).ToListAsync();

// All versions (bypass temporal filtering)
var allVersions = await _context.AllVersions<Contract>()
    .Where(c => c.ContractNumber == "C-001")
    .OrderBy(c => c.ValidFrom)
    .ToListAsync();

// Data within a date range
var rangeData = await _context.ValidBetween<Contract>(startDate, endDate).ToListAsync();

Temporal Operations

// Add with effective date
_context.AddTemporal(contract, effectiveFrom: DateTime.UtcNow);

// Create new version (closes old, opens new)
var newVersion = _context.CreateNewVersion(existing, changes, effectiveDate);

// Terminate (close validity)
_context.Terminate(contract, terminationDate: DateTime.UtcNow);

await _context.SaveChangesAsync();

πŸ”„ Mixed Usage: Sharded + Regular Entities

DTDE works seamlessly alongside regular EF Core entities:

public class AppDbContext : DtdeDbContext
{
    public DbSet<Customer> Customers => Set<Customer>();   // Sharded
    public DbSet<Contract> Contracts => Set<Contract>();   // Temporal
    public DbSet<AuditLog> AuditLogs => Set<AuditLog>();   // Regular EF Core
}
Entity Configuration Behavior
ShardBy() configured Queries routed by shard key
HasTemporalValidity() configured Temporal filtering applied
No special configuration Standard EF Core entity
Direct DbSet<T> access Bypasses DTDE filtering

πŸ—„οΈ Shard Tiers

Organize shards by access frequency for cost optimization:

dtde.AddShard(s => s
    .WithId("2024-current")
    .WithTier(ShardTier.Hot)         // Frequently accessed, recent data
    .WithConnectionString(fastStorage));

dtde.AddShard(s => s
    .WithId("2023-archive")
    .WithTier(ShardTier.Cold)        // Archived, rarely accessed
    .WithConnectionString(cheapStorage)
    .AsReadOnly());                   // Prevent accidental writes
Tier Description Typical Storage
Hot Frequently accessed, recent data SSD, Premium SQL
Warm Less frequently accessed Standard SQL
Cold Archived, rarely accessed Archive storage
Archive Long-term retention Cold storage

βš™οΈ Configuration Options

Fluent API

options.UseDtde(dtde =>
{
    // Entity configuration
    dtde.ConfigureEntity<Order>(e => e.ShardByDate(o => o.OrderDate));

    // Shard definitions
    dtde.AddShard(s => s.WithId("primary").WithConnectionString("..."));

    // Load from configuration file
    dtde.AddShardsFromConfig("shards.json");

    // Default temporal context
    dtde.SetDefaultTemporalContext(() => DateTime.UtcNow);

    // Performance tuning
    dtde.SetMaxParallelShards(10);

    // Diagnostics
    dtde.EnableDiagnostics();
});

JSON Configuration (shards.json)

{
  "shards": [
    {
      "shardId": "2024-q4",
      "name": "Q4 2024 Data",
      "connectionString": "Server=...;Database=Data2024Q4",
      "tier": "Hot",
      "dateRangeStart": "2024-10-01",
      "dateRangeEnd": "2024-12-31",
      "isReadOnly": false,
      "priority": 100
    },
    {
      "shardId": "2024-archive",
      "name": "2024 Archive",
      "connectionString": "Server=...;Database=Archive2024",
      "tier": "Cold",
      "isReadOnly": true,
      "priority": 10
    }
  ]
}

πŸ“Š Performance Benchmarks

Comprehensive benchmarks comparing single table vs sharded approaches:

Test Environment

Component Specification
CPU 12th Gen Intel Core i9-12900H (14 cores, 20 threads)
Runtime .NET 9.0, RyuJIT AVX2
Database SQLite (file-based, separate DBs per benchmark)
Framework BenchmarkDotNet 0.15.0

Key Results

Query Type Records Single Table Sharded Improvement
Point Lookup 100K 143.9 ns 146.5 ns ~Same
Date Range (1 month) 100K 16,103 Β΅s 3,596 Β΅s 4.5x faster
Region Scan 100K 3,659 Β΅s 1,786 Β΅s 2.0x faster
Count 50K 3,534 Β΅s 26.0 Β΅s 136x faster

Key insight: Sharded queries benefit significantly from partition pruning β€” queries that target a specific shard key value only scan relevant partitions.

When to Use Sharding

βœ… Good candidates:

  • Large datasets (millions+ rows)
  • Time-series / temporal data
  • Multi-tenant applications
  • Geographic distribution requirements
  • High write throughput needs
  • Hot/cold data patterns

⚠️ Consider carefully:

  • Small datasets (<100K rows)
  • Random access patterns
  • Complex cross-entity joins
  • Simple CRUD applications
# Run benchmarks
cd benchmarks/Dtde.Benchmarks
dotnet run -c Release

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Your Application                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                   Dtde.EntityFramework                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚DtdeDbContextβ”‚  β”‚Query Engine β”‚  β”‚   Update Engine     β”‚  β”‚
β”‚  β”‚  - ValidAt  β”‚  β”‚ - Rewriter  β”‚  β”‚  - VersionManager   β”‚  β”‚
β”‚  β”‚  - AllVersionsβ”‚ β”‚ - Executor  β”‚  β”‚  - ShardRouter     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                      Dtde.Core                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Metadata   β”‚  β”‚  Sharding   β”‚  β”‚     Temporal        β”‚  β”‚
β”‚  β”‚  Registry   β”‚  β”‚  Strategies β”‚  β”‚     Context         β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                   Dtde.Abstractions                          β”‚
β”‚         Interfaces β€’ Contracts β€’ Exceptions                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Project Structure

dtde/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ Dtde.Abstractions/        # Core interfaces and contracts
β”‚   β”œβ”€β”€ Dtde.Core/                # Core implementations
β”‚   └── Dtde.EntityFramework/     # EF Core integration
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ Dtde.Core.Tests/          # Unit tests
β”‚   β”œβ”€β”€ Dtde.EntityFramework.Tests/
β”‚   └── Dtde.Integration.Tests/
β”œβ”€β”€ samples/                       # Sample applications
β”‚   β”œβ”€β”€ Dtde.Sample.WebApi/       # Basic getting started
β”‚   β”œβ”€β”€ Dtde.Samples.RegionSharding/   # Property-based sharding
β”‚   β”œβ”€β”€ Dtde.Samples.DateSharding/     # Date-based sharding
β”‚   β”œβ”€β”€ Dtde.Samples.HashSharding/     # Hash-based sharding
β”‚   β”œβ”€β”€ Dtde.Samples.MultiTenant/      # Multi-tenancy
β”‚   └── Dtde.Samples.Combined/         # Mixed strategies
β”œβ”€β”€ benchmarks/
β”‚   └── Dtde.Benchmarks/          # Performance benchmarks
└── docs/                         # Documentation (MkDocs)

πŸ’‘ Sample Projects

Explore working examples for each sharding strategy:

Sample Strategy Use Case
Dtde.Sample.WebApi Basic Getting started
Dtde.Samples.RegionSharding Property-based Multi-region data residency
Dtde.Samples.DateSharding Date-based Time-series, audit logs
Dtde.Samples.HashSharding Hash-based Even data distribution
Dtde.Samples.MultiTenant Tenant-based SaaS multi-tenancy
Dtde.Samples.Combined Mixed Complex enterprise scenarios

πŸ§ͺ Testing

# Run all tests (101 tests)
dotnet test

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run specific test project
dotnet test tests/Dtde.Core.Tests/

πŸ“š Documentation


🀝 Contributing

Contributions are welcome! Please read our Contributing Guide before submitting PRs.

# Clone and build
git clone https://github.com/yohasacura/dtde.git
cd dtde
dotnet build
dotnet test

See also:


πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.


πŸ™ Acknowledgments


<div align="center">

Made with ❀️ for the .NET community

⭐ Star on GitHub Β· πŸ› Report Bug Β· πŸ’¬ Discussions

</div>

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 is compatible.  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 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 (2)

Showing the top 2 NuGet packages that depend on Dtde.Abstractions:

Package Downloads
Dtde.Core

DTDE Core - Core implementations of the Distributed Temporal Data Engine including sharding strategies (hash, range, date-based), temporal versioning, and data distribution algorithms.

Dtde.EntityFramework

DTDE Entity Framework Core Integration - Seamlessly integrate horizontal sharding and temporal versioning into your EF Core applications. Supports transparent query routing, automatic data distribution, and point-in-time queries.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 146 12/12/2025