LiteDB
The Shiny.DocumentDb.LiteDb package provides a LiteDB-backed document store. LiteDB is a pure-managed, file-based NoSQL embedded database — no native dependencies, no install steps, works on every .NET-supported platform out of the box.
When to Use
Section titled “When to Use”- Embedded apps that want zero native dependencies (managed-only, AOT-friendlier deployments)
- Small datasets (a few thousand documents) where client-side predicate evaluation is acceptable
- Windows-only apps where SQLite native loading is awkward
- Quick prototypes / sample apps
For larger datasets or server-side predicate translation, prefer SQLite or a SQL provider.
Installation
Section titled “Installation”dotnet add package Shiny.DocumentDb.LiteDb-
Direct instantiation
using Shiny.DocumentDb.LiteDb;var store = new LiteDbDocumentStore(new LiteDbDocumentStoreOptions{ConnectionString = "Filename=mydata.db"}); -
Dependency injection
LiteDB uses its own options class — register the store directly:
builder.Services.AddSingleton(new LiteDbDocumentStoreOptions{ConnectionString = "Filename=mydata.db"}.MapTypeToCollection<User>().MapTypeToCollection<Order>("orders"));builder.Services.AddSingleton<IDocumentStore, LiteDbDocumentStore>();
Options Reference
Section titled “Options Reference”| Property | Type | Default | Description |
|---|---|---|---|
ConnectionString | string | (required) | LiteDB connection string. Use Filename=path.db for file-based storage or Filename=:memory: for in-memory |
CollectionName | string | "documents" | Default collection for unmapped types |
TypeNameResolution | TypeNameResolution | ShortName | How type names are stored |
JsonSerializerOptions | JsonSerializerOptions? | null | JSON serialization settings |
UseReflectionFallback | bool | true | Set to false for AOT safety |
Logging | Action<string>? | null | Diagnostic callback |
Collection-Per-Type Mapping
Section titled “Collection-Per-Type Mapping”new LiteDbDocumentStoreOptions{ ConnectionString = "Filename=mydata.db"}.MapTypeToCollection<User>() // auto-derived.MapTypeToCollection<Order>("orders") // explicit name.MapTypeToCollection<Sensor>("sensors", s => s.DeviceKey) // explicit name + custom IdStorage Layout
Section titled “Storage Layout”Documents are stored as BsonDocument records inside LiteDB collections. Each document carries the same envelope fields as the SQL providers (Id, TypeName, Data, CreatedAt, UpdatedAt) — Data is a real BsonDocument sub-object, not a stringified blob.
Queries
Section titled “Queries”LiteDB does not translate LINQ predicates to a query language. The provider:
- Loads every document of the requested type into memory (filtered only by
TypeName/ collection) - Applies the compiled predicate in C#
- Applies ordering, pagination, and projection in C#
// Fine for small datasetsvar users = await store.Query<User>() .Where(u => u.Age > 25) .OrderBy(u => u.Name) .Paginate(0, 50) .ToList();For datasets larger than a few thousand documents, expect linear scans on every query. There is no way to push a predicate down.
Backup
Section titled “Backup”LiteDbDocumentStore.Backup(path) copies the database to a file. Requires a file-based connection string with a Filename parameter (not available on :memory: stores).
var store = new LiteDbDocumentStore(new LiteDbDocumentStoreOptions{ ConnectionString = "Filename=mydata.db"});await store.Backup("/path/to/backup.db");Backup lives on the concrete LiteDbDocumentStore type, not on IDocumentStore.
Optimistic Concurrency
Section titled “Optimistic Concurrency”MapVersionProperty<T> on LiteDbDocumentStoreOptions enables document-level version checks. Version is stored inside the BSON document — no schema changes required.
new LiteDbDocumentStoreOptions{ ConnectionString = "Filename=mydata.db"}.MapVersionProperty<Order>(o => o.RowVersion);Limitations
Section titled “Limitations”- All predicates evaluated in C# after a full load — fine for small datasets, painful for large ones.
- No raw SQL —
Query<T>(string)andQueryStream<T>(string)throwNotSupportedException. - No spatial —
WithinRadius/WithinBoundingBox/NearestNeighborsthrowNotSupportedException. - No
CreateIndexAsync— LiteDB indexes are managed natively if needed. - Single-process — opening the same file from two processes fails.
- Pure-managed binary — no native dependencies, no native loader required.
- Optimistic concurrency works the same way as on the SQL providers.
Upsertdeep-merges in C# with recursive null stripping (matches CosmosDB / MongoDB / IndexedDB semantics).