EntglDb supports multiple persistence backends through a clean abstraction layer. Choose the provider that best fits your deployment scenario.
| Provider | Package | Best For | Target Framework |
|---|---|---|---|
| BLite | EntglDb.Persistence.BLite |
Embedded/desktop/mobile/edge | net10.0 |
| EF Core | EntglDb.Persistence.EntityFramework |
Cloud/enterprise, multi-database | net10.0 |
Both providers share the same abstract interfaces (IDocumentStore, IOplogStore, ISnapshotMetadataStore, IDocumentMetadataStore), making it straightforward to switch between them or implement a custom provider.
Package: EntglDb.Persistence.BLite
BLite is a high-performance embedded BSON document database with zero external dependencies. It is the recommended provider for embedded, desktop, mobile, and edge scenarios.
- ✅ Zero configuration: Works out of the box, single file database
- ✅ High performance: Native BSON engine, no ORM overhead
- ✅ Full async: Async read/write operations (v1.1+)
- ✅ Per-collection tables: Dynamic database paths for better isolation (v2.0+)
- ✅ Snapshots: Fast reconnection with
SnapshotMetadata - ✅ ACID: Write-Ahead Logging (WAL) for consistency
- ✅ Vector search: HNSW index support
- ✅ Cross-platform: Windows, Linux, macOS
- Desktop applications (Avalonia, WPF, WinForms)
- Mobile applications (.NET MAUI)
- Edge computing and IoT
- Development and testing
- Offline-first scenarios where portability matters
// Register BLite persistence with DI
builder.Services
.AddEntglDbCore()
.AddEntglDbBLite<MyDbContext, MyDocumentStore>(
sp => new MyDbContext("mydata.blite"));Extend BLiteDocumentStore<T> to create your sync bridge:
public class MyDocumentStore : BLiteDocumentStore<MyDbContext>
{
public MyDocumentStore(
MyDbContext context,
IPeerNodeConfigurationProvider configProvider,
IVectorClockService vectorClockService,
ILogger<MyDocumentStore>? logger = null)
: base(context, configProvider, vectorClockService, logger: logger)
{
WatchCollection("Users", context.Users, u => u.Id);
}
protected override async Task ApplyContentToEntityAsync(
string collection, string key, JsonElement content, CancellationToken ct)
{
// Map incoming JSON to your entity and upsert
}
// Implement remaining abstract methods...
}Package: EntglDb.Persistence.EntityFramework
The EF Core provider enables EntglDb to work with any database supported by Entity Framework Core, including SQL Server, PostgreSQL, MySQL, and SQLite.
- ✅ Multi-database support: SQL Server, PostgreSQL, MySQL, SQLite
- ✅ EF Core benefits: Migrations, LINQ, change tracking
- ✅ Type-safe: Strongly-typed entities
- ✅ Production-grade: Connection pooling, retry logic
⚠️ JSON queries: Complex JSON queries evaluated in-memory
- Cloud deployments (Azure SQL, AWS RDS, etc.)
- Enterprise applications with existing SQL infrastructure
- Multi-tenant SaaS scenarios
- Teams already familiar with EF Core
- When database portability is important
builder.Services.AddEntglDbEntityFramework(options =>
{
options.UseSqlServer(
"Server=localhost;Database=EntglDb;Integrated Security=true");
});builder.Services.AddDbContext<EntglDbContext>(options =>
options.UseNpgsql(connectionString));
builder.Services.AddEntglDbEntityFramework();var serverVersion = ServerVersion.AutoDetect(connectionString);
builder.Services.AddEntglDbEntityFrameworkMySql(connectionString, serverVersion);builder.Services.AddEntglDbEntityFrameworkSqlite("Data Source=entgldb.db");dotnet ef migrations add InitialCreate --context EntglDbContext
dotnet ef database update --context EntglDbContextExtend EfCoreDocumentStore<T> for EF Core:
public class MyDocumentStore : EfCoreDocumentStore<MyEfDbContext>
{
public MyDocumentStore(
MyEfDbContext context,
IPeerNodeConfigurationProvider configProvider,
IVectorClockService vectorClockService,
ILogger<MyDocumentStore>? logger = null)
: base(context, configProvider, vectorClockService, logger: logger)
{
WatchCollection("Products", /* ... */);
}
// Implement abstract methods...
}| Feature | BLite | EF Core |
|---|---|---|
| Storage Format | BSON file-based | Varies (SQL Server, PostgreSQL, etc.) |
| Setup Complexity | Zero config | Connection string + migrations |
| Performance | Excellent (native) | Good (ORM overhead) |
| JSON Storage | Native BSON | TEXT/NVARCHAR/JSONB |
| Async Operations | Full async (v1.1+) | Full async |
| ContentHash | ✅ (v2.1+) | ✅ (v2.1+) |
| Snapshot Support | ✅ | ✅ |
| Per-Collection Tables | ✅ (v2.0+) | Standard EF models |
| Vector Search (HNSW) | ✅ | ❌ |
| Horizontal Scaling | No | Yes (database-dependent) |
| Connection Pooling | N/A | Built-in |
| Cloud Deployment | Possible (file storage) | Recommended |
You can implement a custom persistence provider by implementing the core interfaces:
public interface IDocumentStore
{
Task PutAsync(string collection, string key, JsonElement content, CancellationToken ct);
Task<JsonElement?> GetAsync(string collection, string key, CancellationToken ct);
Task DeleteAsync(string collection, string key, CancellationToken ct);
// ...
}
public interface IOplogStore
{
Task AppendAsync(OplogEntry entry, CancellationToken ct);
Task<IEnumerable<OplogEntry>> GetEntriesAfterAsync(HlcTimestamp after, CancellationToken ct);
// ...
}- Use BLite: Fast, zero config, disposable, no server required
- Use BLite: Best performance, single file, cross-platform, vector search
- Use EF Core: SQL Server or PostgreSQL for production workloads with managed database services
- Use EF Core + ASP.NET Core Multi-Cluster: Isolated databases per tenant with shared hosting
- Ensure only one process accesses the BLite file at a time
- Use per-collection tables (v2.0+) for better isolation
- Expected for complex JSON queries
- Use simple equality/comparison operators for best performance
- Consider adding database indexes on frequently queried properties
- Increase
Maximum Pool Sizein connection string - Ensure DbContext instances are properly disposed
- For PostgreSQL, consider PgBouncer for connection pooling