A C# library for synchronizing data between databases using delta encoding.
Target Framework: .NET 10.0
| Component | Version |
|---|---|
| EF Core | 10.0.0 |
| PostgreSQL | 10.0.0 |
| MySQL (Oracle) | 10.0.1 |
| SQLite | 10.0.0 |
| SQL Server | 10.0.0 |
SyncFramework uses delta-based synchronization to efficiently sync data between databases.
graph TB
subgraph "Client"
A[Client Application] --> B[DbContext]
B --> C[Custom BatchExecutor]
C -->|Intercept SQL| D[Delta Generator]
D -->|Store Deltas| E[Delta Store]
E -->|Push Deltas| F[HTTP Client]
end
subgraph "Server"
F -->|HTTP| G[SyncServer]
G -->|Store Deltas| H[Server Delta Store]
H -->|Provide Deltas| G
end
subgraph "Other Clients"
G -->|HTTP| I[Other Clients]
I -->|Push Deltas| G
end
style A fill:#d4f1f9,stroke:#333
style G fill:#ffcccc,stroke:#333
SyncFramework replaces EF Core's internal BatchExecutor with a custom one that intercepts generated SQL commands (deltas), stores them, and makes them available for replay on remote databases — even across different database engines.
dotnet add package BIT.Data.Sync.EfCore.SqlServer # SQL Server
dotnet add package BIT.Data.Sync.EfCore.Sqlite # SQLite
dotnet add package BIT.Data.Sync.EfCore.Npgsql # PostgreSQL
dotnet add package BIT.Data.Sync.EfCore.MySql # MySQL (Oracle)var services = new ServiceCollection();
var httpClient = new HttpClient { BaseAddress = new Uri("https://your-sync-server/") };
services.AddSyncFrameworkForSQLite(
connectionString: "Data Source=deltas.db;",
httpClient: httpClient,
serverNodeId: "MemoryDeltaStore1",
identity: "my-client-id",
new SqliteDeltaGenerator(),
new SqlServerDeltaGenerator()
);
var serviceProvider = services.BuildServiceProvider();var options = new DbContextOptionsBuilder().UseSqlite("Data Source=myapp.db;").Options;
var ctx = new MyDbContext(options, serviceProvider);
await ctx.Database.EnsureCreatedAsync();await ctx.PushAsync(); // send local deltas to server
await ctx.PullAsync(); // fetch + apply server deltas locally
await ctx.FetchAsync(); // fetch deltas without applying// Program.cs / Startup.cs
services.AddSyncServerWithMemoryNode("MemoryDeltaStore1");// SyncController.cs
[ApiController]
[Route("sync")]
public class SyncController : SyncControllerBase
{
public SyncController(ILogger<SyncControllerBase> logger, ISyncFrameworkServer server)
: base(logger, server) { }
}src/Tools/SyncFramework.Dashboard is a Blazor Server admin UI for managing sync server nodes.
cd src/Tools/SyncFramework.Dashboard
ASPNETCORE_ENVIRONMENT=Development dotnet run
# Open http://localhost:5000| Page | Route | Description |
|---|---|---|
| Nodes | / |
View all active nodes and delta counts |
| Add Node | /nodes/add |
Spin up a new node (Memory or SQLite) |
| Replay | /nodes/{id}/replay |
Replay a node's deltas into a SQLite file |
Nodes — overview of all active sync nodes

Add Node — spin up a new node with store type selection

Replay — apply a node's deltas into a local SQLite file

- Data Synchronization in a Few Words
- Parts of a Synchronization Framework
- Let's Write a Synchronization Framework in C#
- Synchronization Framework Base Classes
- Planning the First Implementation
- Testing the First Implementation (Video)
- Adding Network Support
All notable changes are documented in CHANGELOG.md, following the Keep a Changelog format.
When opening a PR or making a commit that changes behavior:
- Add an entry under the
[Unreleased]section at the top ofCHANGELOG.md - Use the appropriate category:
- Added — new features
- Changed — changes to existing behavior
- Deprecated — soon-to-be removed features
- Removed — removed features
- Fixed — bug fixes
- Security — vulnerability fixes
- Breaking Changes — changes that break backward compatibility
- On release, rename
[Unreleased]to the version number and date, e.g.[10.1.0] — 2026-05-01
Example entry:
## [Unreleased]
### Added
- `IDeltaStore.PurgeAsync` — bulk delete deltas older than a given date
### Fixed
- Replay page now handles empty delta stores without crashingdotnet new install BIT.Data.Sync.Templates
dotnet new SyncServer -o MySyncServer