Skip to content
Document DB v7.2: Temporal Support, Telemetry Collection, All Calculations, String Based APIs, & Orleans Storage Providers! Feed The Machine Here

Why DocumentDb

If you are storing data in a .NET app today, you are most likely reaching for sqlite-net-pcl (the de-facto mobile SQLite ORM) or Entity Framework Core (the default relational stack on the server). Shiny.DocumentDb is a different shape of tool: a schema-free document store that persists entire object graphs — nested objects and child collections — as a single JSON document, queryable with LINQ, across ten database backends, under full AOT and trimming.

This page lays out, honestly, where each tool fits and where DocumentDb pulls ahead.

CapabilityShiny.DocumentDbsqlite-net-pclEF Core
Schema managementZero — store objects directlyAuto-creates flat tables from POCOsMigrations (Add-Migration / Update-Database)
Nested objects & child collectionsOne JSON document, one read/writeNot supported — separate tables + manual joinsOwned types / related entities + JOINs
LINQ on nested dataWhere(o => o.Lines.Any(l => l.Price > 10))Not possibleYes, via Include() + LINQ→SQL
Database providersSQLite, LiteDB, CosmosDB, MongoDB, DuckDB, IndexedDB, MySQL, SQL Server, PostgreSQL, OracleSQLite onlyMany relational + CosmosDB
AOT / trimmingFirst-class — source-generated JSON, zero reflectionReflection-based; no AOT support[RequiresDynamicCode] / [RequiresUnreferencedCode]; no full AOT
MigrationsNone — schema-free JSONManual (you own every ALTER)First-class, but required for every schema change
Change trackingNone — snapshot writesNoneFull graph tracking (powerful, but has a cost)
Compiled queriesN/A — expressions compile to SQL strings via a visitor, no per-query JITN/AYes — EF.CompileAsyncQuery
ProjectionsSQL-level json_object via .Select()Manual.Select()
Transactionsstore.RunInTransaction(...)RunInTransactionAsyncSaveChanges / explicit transactions
Vector / ANN searchYes — cross-provider (pgvector, sqlite-vec, DiskANN, …)NoProvider-specific only
Temporal historyYes — MapTemporal (history / as-of / diff / restore)NoSQL Server temporal tables only
TelemetryBuilt-in OpenTelemetry metrics + spansNoEF diagnostics / interceptors
Dependency footprintCore + one provider packageSingle small packageLarge transitive graph
Startup costOpen a connection and goOpen a connection and goDbContext model building + migration checks
Best fitObject graphs, nested data, mobile/offline, multi-providerSimple flat-table CRUD on mobileServer-side relational apps

Nested data is free. An order with a shipping address, line items, and tags is one document. One Insert, one Get, one round trip. sqlite-net forces you into three normalized tables with foreign keys and manual rehydration on every read; EF Core models the relationships for you but still pays for multi-table JOINs and change-tracking graph fixup. The benchmarks below show this gap widening as the graph grows.

No migrations, no model building. On a mobile device the database is created on first launch — there is no DBA, no staging environment, no rollback plan. EF Core’s migration pipeline adds ceremony with no payoff in that world, and its OnModelCreating reflection runs at startup. DocumentDb opens a connection and is ready.

AOT and trimming actually work. Apple platforms prohibit JIT outright; Android benefits heavily from AOT. EF Core is reflection- and dynamic-code-heavy and carries trim/AOT-hostile attributes throughout its API; sqlite-net relies on reflection too. DocumentDb uses source-generated JsonTypeInfo<T> on every API and translates LINQ to SQL with a visitor — no Expression.Compile(), no Reflection.Emit.

One API, ten backends. The same code runs on SQLite on a phone and PostgreSQL on a server. sqlite-net is SQLite-only; EF Core spans relational engines but with provider-specific quirks and a heavier footprint.

Measured with BenchmarkDotNet v0.15.8 on Apple M5 Pro, .NET 10.0.8, macOS. All three libraries run against SQLite. EF Core uses its fastest read path: pre-compiled EF.CompileAsyncQuery queries with AsNoTracking. Source lives in the benchmarks/ folder of the repo.

A plain User { Id, Name, Age, Email } — the case where sqlite-net and EF Core are at their strongest, because they read native indexed columns while the document store extracts from JSON.

Library101001000
Shiny.DocumentDb420 µs3.59 ms36.05 ms
EF Core873 µs7.49 ms115.70 ms
sqlite-net1.72 ms17.22 ms190.47 ms
OperationShiny.DocumentDbEF Core (compiled)sqlite-net
Get by Id2.79 µs8.24 µs10.95 µs
Get all (1000)502.58 µs319.84 µs297.52 µs
Query by name (1000)165.55 µs25.41 µs30.53 µs

Nested object graph (Order → Address + Order Lines + Tags)

Section titled “Nested object graph (Order → Address + Order Lines + Tags)”

One order with a shipping address, three line items, and two tags. sqlite-net stores this across 3 tables (6 inserts per order, 3 queries + manual rehydration per read). EF Core models it as related entities read with Include. DocumentDb stores it as one JSON document.

Library101001000
Shiny.DocumentDb439 µs3.83 ms39.02 ms
EF Core (3 tables)4.00 ms24.74 ms661.10 ms
sqlite-net (3 tables)11.94 ms123.33 ms2.52 s

At 1,000 orders the document store is ~17x faster than EF Core and ~65x faster than sqlite-net.

OperationShiny.DocumentDbsqlite-netEF Core (Include, compiled)
Get by Id3.62 µs28.10 µs31.00 µs
Get all (100)124.3 µs207.8 µs1.14 ms
Get all (1000)1.27 ms1.78 ms11.89 ms
Query by status (~500/1000)1.01 ms1.41 ms5.82 ms

The document store wins every nested read — by 8–10x against EF Core’s Include joins — because the whole graph lives in one row and deserializes in a single pass, with no JOINs and no change-tracker graph fixup.

  • Choose Shiny.DocumentDb when your data is document-shaped (nested objects, child collections, variable structure), when you target .NET MAUI / AOT, when you want one storage API across multiple databases, or when you want vector search, temporal history, or built-in telemetry without bolting on more libraries.
  • Choose sqlite-net-pcl for the simplest possible flat-table CRUD on a single SQLite database, where every entity is a handful of scalar columns and you never store an object graph.
  • Choose EF Core for server-side relational applications with complex cross-entity queries, reporting, and a relational schema you genuinely want to model and migrate.

DocumentDb is not trying to replace a relational mapper for relational problems. It is the right tool when your objects are the model and the database is just where they live.