![]() |
VOOZH | about |
dotnet add package LiteDbX.Encryption.Gcm --version 2.0.0
NuGet\Install-Package LiteDbX.Encryption.Gcm -Version 2.0.0
<PackageReference Include="LiteDbX.Encryption.Gcm" Version="2.0.0" />
<PackageVersion Include="LiteDbX.Encryption.Gcm" Version="2.0.0" />Directory.Packages.props
<PackageReference Include="LiteDbX.Encryption.Gcm" />Project file
paket add LiteDbX.Encryption.Gcm --version 2.0.0
#r "nuget: LiteDbX.Encryption.Gcm, 2.0.0"
#:package LiteDbX.Encryption.Gcm@2.0.0
#addin nuget:?package=LiteDbX.Encryption.Gcm&version=2.0.0Install as a Cake Addin
#tool nuget:?package=LiteDbX.Encryption.Gcm&version=2.0.0Install as a Cake Tool
👁 NuGet Version
👁 NuGet Downloads
👁 NuGet Version
LiteDbX is a modern rewrite/evolution of LiteDB focused on an async-first embedded document database for .NET.
Today the project includes:
ValueTask and IAsyncEnumerable<T>ILiteTransaction scopes instead of thread-bound BeginTrans / Commit / RollbackQuery() builder plus a provider-backed AsQueryable() LINQ surfaceILiteStorage<TFileId> and ILiteFileHandle<TFileId>LiteDbX.Encryption.Gcm packageCurrent status
LiteDbX now exposes dual lifecycle entry points: open databases with
LiteDatabase.Open(...)/LiteDatabase.OpenAsync(...),LiteRepository.Open(...)/LiteRepository.OpenAsync(...), orLiteEngine.Open(...)/LiteEngine.OpenAsync(...), use async CRUD/query APIs, and dispose withawait using. The material underdocs/async-redesign/remains useful as design history and implementation background, but the current API now supports synchronous open for constructor/startup boundaries while keeping data access async.
Core package:
Install-Package LiteDbX
Optional AES-GCM provider:
Install-Package LiteDbX.Encryption.Gcm
Current targets in this repository are:
netstandard2.0netstandard2.1net10.0LiteDbX data operations are async. Open can be synchronous or asynchronous; disposal remains async.
The canonical entry points are:
LiteDatabase.Open(...) / await LiteDatabase.OpenAsync(...)LiteRepository.Open(...) / await LiteRepository.OpenAsync(...)LiteEngine.Open(...) / await LiteEngine.OpenAsync(...)public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string[] Phones { get; set; }
public bool IsActive { get; set; }
}
await using var db = await LiteDatabase.OpenAsync(@"MyData.db");
var customers = db.GetCollection<Customer>("customers");
await customers.EnsureIndex(x => x.Name, unique: true);
var customer = new Customer
{
Name = "John Doe",
Phones = new[] { "8000-0000", "9000-0000" },
Age = 39,
IsActive = true
};
var id = await customers.Insert(customer);
var activeAdults = await customers.Query()
.Where(x => x.IsActive && x.Age >= 18)
.OrderBy(x => x.Name)
.ToList();
await foreach (var row in customers.Find(x => x.IsActive))
{
Console.WriteLine($"{row.Name} ({row.Age})");
}
BsonMapper exposes serialization switches that let you tune document shape.
Two useful examples are:
EmptyStringToNull - converts empty strings to BSON nullDontSerializeEmptyCollections - omits empty collection members from serialized documentsvar mapper = new BsonMapper
{
EmptyStringToNull = true,
DontSerializeEmptyCollections = true
};
var doc = mapper.ToDocument(new
{
Name = "",
Tags = new string[0],
Scores = new Dictionary<string, int>()
});
With DontSerializeEmptyCollections = true:
mapper.Serialize(new List<int>()) still produces []SerializeNullValues still controls null member handling:
SerializeNullValues = false, null members are omittedSerializeNullValues = true, null members are written as BSON nullDontSerializeEmptyCollections = trueLiteDbX no longer centers transactions around thread affinity.
Use BeginTransaction() and the returned ILiteTransaction scope.
await using var db = await LiteDatabase.OpenAsync(@"MyData.db");
var customers = db.GetCollection<Customer>("customers");
await using var tx = await db.BeginTransaction();
await customers.Insert(new Customer
{
Name = "Ana",
Age = 28,
IsActive = true
}, tx);
var names = await customers.Query(tx)
.Where(x => x.IsActive)
.Select(x => x.Name)
.ToList();
await tx.Commit();
If the transaction scope is disposed before Commit(), LiteDbX rolls it back.
Prefer this pattern everywhere:
await using var db = await LiteDatabase.OpenAsync("filename=my-data.db");
If you must cross a synchronous boundary such as a constructor, use:
await using var db = LiteDatabase.Open("filename=my-data.db");
For repository-style code, prefer:
await using var repo = await LiteRepository.OpenAsync("filename=my-data.db");
Lifecycle notes:
Open(...) when the caller must stay synchronousOpenAsync(...) when you want non-blocking startupPragma(...) APIsawait using / DisposeAsync()Query() and provider-backed LINQLiteDbX exposes two complementary query surfaces:
collection.Query() — the native LiteDbX query buildercollection.AsQueryable() — a provider-backed IQueryable<T> adapter for supported LINQ shapesAsQueryable() does not replace Query().
Provider-backed LINQ lowers back into the same native query model used by Query().
Query() when you wantBsonExpression controlNative query composition remains synchronous, but execution is async-only. Typical terminals include:
ToEnumerable()ToDocuments()ToList()ToArray()First() / FirstOrDefault()Single() / SingleOrDefault()Count() / LongCount() / Exists()GetPlan()AsQueryable() when you wantvar rows = await customers
.AsQueryable()
.Where(x => x.IsActive)
.OrderBy(x => x.Name)
.Select(x => new { x.Id, x.Name })
.ToListAsync();
Transaction-aware roots are available too:
await using var tx = await db.BeginTransaction();
var names = await customers
.AsQueryable(tx)
.Where(x => x.IsActive)
.Select(x => x.Name)
.ToArrayAsync();
IQueryable<T>Provider-backed LINQ composes synchronously but executes asynchronously via LiteDbX extension methods such as:
ToAsyncEnumerable()ToListAsync()ToArrayAsync()FirstAsync()FirstOrDefaultAsync()SingleAsync()SingleOrDefaultAsync()AnyAsync()CountAsync()LongCountAsync()GetPlanAsync()Do not rely on synchronous enumeration or synchronous LINQ materialization for provider-backed LiteDbX queries. Those paths are expected to fail clearly rather than silently doing sync-over-async work.
The current provider is intentionally narrower than full LINQ-to-Objects or EF-style providers.
Supported core operators include:
WhereSelectOrderByOrderByDescendingThenByThenByDescendingSkipTakeSupported grouped LINQ is intentionally narrow and engine-aligned:
GroupBy(key)Where(...) lowering to native HAVINGSelect(g => new { g.Key, Count = g.Count() })Select(g => new { g.Key, Sum = g.Sum(x => x.SomeField) })For unsupported shapes, fall back to collection.Query().
LiteDbX file storage now exposes async-only handles instead of a public Stream subclass.
db.FileStorage gives you the default storage using _files / _chunksdb.GetStorage<TFileId>(...) gives you a custom file-id type or collection namesOpenRead(...) / OpenWrite(...) return ILiteFileHandle<TFileId>Upload(...) / Download(...) remain asyncawait using var db = await LiteDatabase.OpenAsync(@"MyData.db");
await using var writer = await db.FileStorage.OpenWrite("readme-demo", "demo.txt");
await writer.Write(System.Text.Encoding.UTF8.GetBytes("hello LiteDbX"));
await writer.Flush();
LiteDbX currently supports two AES-based encrypted file modes:
ECB — built into the core LiteDbX packageGCM — provided by the optional LiteDbX.Encryption.Gcm packageTo use GCM:
LiteDbX.Encryption.GcmGcmEncryptionRegistration.Register() once at startupAESEncryption = AESEncryptionType.GCMusing LiteDbX.Encryption.Gcm;
GcmEncryptionRegistration.Register();
var cs = new ConnectionString("filename=secure.db;password=secret;encryption=GCM");
await using var db = await LiteDatabase.OpenAsync(cs);
Important notes:
For more detail, see:
docs/gcm-setup.mddocs/aes-gcm-mode.mdLiteDbX currently supports three connection types:
| Mode | Intended use | Cross-process guarantee | Explicit ILiteTransaction support |
|---|---|---|---|
ConnectionType.Direct |
normal dedicated engine access | none beyond normal file semantics | ✅ Supported |
ConnectionType.Shared |
async-safe serialized access inside one process | ❌ No — in-process only | ❌ Not supported |
ConnectionType.LockFile |
physical-file cross-process write coordination | ✅ Yes, via lock file | ❌ Not supported |
Additional notes:
Shared is a supported in-process mode. It no longer implies the old named-mutex cross-process behaviour.LockFile is supported only for physical filename-based databases; it does not support custom streams, :memory:, or :temp:.Shared and LockFile support nested single-call operations, but not long-lived explicit transaction scope across arbitrary user code.If you need explicit transaction scopes, prefer Direct.
If you need cross-process file coordination, prefer LockFile rather than assuming Shared provides the old named-mutex behavior.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 is compatible. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.