FireForNet.Firebase.Firestore
1.0.1-preview.22
Prefix Reserved
dotnet add package FireForNet.Firebase.Firestore --version 1.0.1-preview.22
NuGet\Install-Package FireForNet.Firebase.Firestore -Version 1.0.1-preview.22
<PackageReference Include="FireForNet.Firebase.Firestore" Version="1.0.1-preview.22" />
<PackageVersion Include="FireForNet.Firebase.Firestore" Version="1.0.1-preview.22" />
<PackageReference Include="FireForNet.Firebase.Firestore" />
paket add FireForNet.Firebase.Firestore --version 1.0.1-preview.22
#r "nuget: FireForNet.Firebase.Firestore, 1.0.1-preview.22"
#:package FireForNet.Firebase.Firestore@1.0.1-preview.22
#addin nuget:?package=FireForNet.Firebase.Firestore&version=1.0.1-preview.22&prerelease
#tool nuget:?package=FireForNet.Firebase.Firestore&version=1.0.1-preview.22&prerelease
FireForNet.Firebase.Firestore
Cloud Firestore for the FireForNet Firebase Client SDK for .NET.
About FireForNet
FireForNet is a platform-agnostic, .NET-native Firebase Client SDK developed as part of the Circuids ecosystem. It provides a consistent Firebase client development experience across .NET application environments, while allowing platform-specific implementations where Firebase requires them.
About This Package
This package provides the Firestore SDK for FireForNet:
- Typed document and collection references
- Queries, snapshots, and listeners
- Batched writes and transactions
- Bundles
- Local store contracts, with platform-agnostic SQLite persistence available as a companion package
- The default WebChannel-capable transport, with a native gRPC (HTTP/2) transport available as an add-on package
Installation
dotnet add package FireForNet.Firebase.Firestore
Targets net10.0. References FireForNet.Firebase.Core transitively.
Setup
builder.Services.AddFirestore();
Platform and transport packages extend the returned FirestoreBuilder:
builder.Services.AddFirestore().UseBlazor(...); // Blazor (all hosting models)
builder.Services.AddFirestore().UseBrowser(); // framework-independent WASM
builder.Services.AddFirestore().UseMaui(); // .NET MAUI
builder.Services.AddFirestore().UseWindows(); // Windows desktop
builder.Services.AddFirestore().UseAndroid(...); // native (non-MAUI) Android
builder.Services.AddFirestore().UseApple(...); // iOS / macOS / Mac Catalyst
builder.Services.AddFirestore().UseSqlite(databasePath); // SQLite persistence
builder.Services.AddFirestore().UseNativeGrpc(); // native gRPC transport add-on
Usage
Resolve IFirestore from DI:
public class ChatRepository(IFirestore firestore)
{
private readonly ICollectionReference<ChatMessage> _rooms =
firestore.Collection<ChatMessage>("rooms");
public async Task<string> AddMessageAsync(string roomId, ChatMessage message)
{
var doc = await _rooms.Document(roomId).Collection<ChatMessage>("messages")
.AddAsync(message);
return doc.Id;
}
public async Task<IReadOnlyList<ChatMessage>> GetRecentAsync(string roomId)
{
var snapshot = await _rooms
.WhereEqualTo("roomId", roomId)
.OrderByDescending("sentAt")
.Limit(50)
.GetAsync();
return snapshot.Documents.Select(d => d.Data).ToList();
}
public async Task ListenAsync(string roomId)
{
var doc = _rooms.Document(roomId);
var listener = await doc.OnSnapshotAsync(snapshot =>
{
var data = snapshot.Data;
// react to updates
});
// stop listening when done:
await listener.DisposeAsync();
}
}
IFirestore also exposes Document<T>(path) for single-document access, RunTransactionAsync<T> for transactions, and batched writes via IWriteBatch.
Related FireForNet Packages
| Package | Purpose |
|---|---|
FireForNet.Firebase.Firestore.Blazor |
Blazor integration (WebAssembly, Server, Hybrid, Auto) |
FireForNet.Firebase.Firestore.Browser |
Framework-independent WASM integration |
FireForNet.Firebase.Firestore.Maui |
.NET MAUI integration |
FireForNet.Firebase.Firestore.Windows |
Windows desktop integration |
FireForNet.Firebase.Firestore.Android |
Native (non-MAUI) Android integration |
FireForNet.Firebase.Firestore.Apple |
Apple native integration (iOS, macOS, Mac Catalyst) |
FireForNet.Firebase.Firestore.Sqlite |
Platform-agnostic SQLite persistence |
FireForNet.Firebase.Firestore.Grpc |
Native gRPC (HTTP/2) transport add-on |
Documentation
Comprehensive FireForNet documentation is being prepared for the Release Candidate stage.
Project Status
FireForNet is currently available as a Preview release and is approaching its Release Candidate milestone. APIs, package structure, and implementation details may continue to evolve before RC and GA.
The RC milestone will be followed by an extensive cross-platform validation and testing phase before the first GA release.
All FireForNet packages are part of a coordinated release train and share the same version number.
Source Availability
FireForNet is currently being developed in a private source repository during the Preview development phase. The source will be made publicly available as the project approaches its open-source phase, with the public repository established from the appropriate release milestone.
Until then, NuGet Preview packages provide the public distribution channel for evaluating and using FireForNet.
License
This package is licensed under the Apache-2.0 license.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FireForNet.Firebase.Core (>= 1.0.1-preview.22)
- Google.Protobuf (>= 3.33.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on FireForNet.Firebase.Firestore:
| Package | Downloads |
|---|---|
|
FireForNet.Firebase.Firestore.Browser
Package Description |
|
|
FireForNet.Firebase.Firestore.Blazor
Package Description |
|
|
FireForNet.Firebase.Firestore.Sqlite
Package Description |
|
|
FireForNet.Firebase.Firestore.Grpc
Native gRPC (HTTP/2) transport addon for FireForNet Firestore SDK |
|
|
FireForNet.Firebase.Firestore.Windows
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.1-preview.22 | 82 | 9/27/2026 |
| 1.0.1-preview.21 | 83 | 9/22/2026 |
| 1.0.1-preview.20 | 83 | 9/18/2026 |
| 1.0.1-preview.19 | 80 | 9/12/2026 |
| 1.0.1-preview.18 | 123 | 8/24/2026 |
| 1.0.1-preview.17 | 101 | 8/9/2026 |
| 1.0.1-preview.16 | 80 | 8/9/2026 |
| 1.0.1-preview.15 | 84 | 8/8/2026 |
| 1.0.1-preview.14 | 88 | 8/8/2026 |
| 1.0.1-preview.13 | 101 | 7/23/2026 |
| 1.0.1-preview.12 | 128 | 7/9/2026 |
| 1.0.1-preview.11 | 105 | 6/29/2026 |
| 1.0.1-preview.10 | 91 | 6/25/2026 |
| 1.0.1-preview.9 | 100 | 6/24/2026 |
| 1.0.1-preview.8 | 94 | 6/23/2026 |
| 1.0.1-preview.7 | 84 | 6/9/2026 |
| 1.0.1-preview.6 | 90 | 6/8/2026 |
| 1.0.1-preview.5 | 98 | 6/8/2026 |
| 1.0.1-preview.4 | 101 | 6/8/2026 |
| 1.0.1-preview.3 | 82 | 6/8/2026 |
v1.0.1-preview.22
- BREAKING: MutationKind, FieldTransformKind, MutationBatchState, and TargetPurposeMessage are readonly record struct wire types with canonical all-lowercase strings ("set", "servertimestamp", "queued", "listen", ...). Enum-only usage (switch patterns, (int) casts) no longer compiles; parsing accepts any casing.
- BREAKING: mutation-batch state persists as canonical strings instead of integer ordinals; cross-tab WatchStreamMessage.targetMismatches values are canonical strings instead of integers.
- BREAKING: dictionary writes, query/cursor/pipeline literals, and object-slot values derive their wire form from scope System.Text.Json behavior instead of ToString() - typed and direct write paths are now coherent (Enum.ToString() never reaches the wire).
- Cross-tab online-state broadcasts use canonical lowercase strings ("online", "offline", "unknown"); reads remain case-insensitive.
- BREAKING: typed writes store explicit nulls - a null model property becomes a null field (JS setDoc/FlutterFire parity). Declare [JsonIgnore(Condition = WhenWritingNull)] per property to keep omitting it.
- Fixed: objects containing byte[]/Timestamp/GeoPoint resolve identically on typed-write and literal paths (__ffnType envelopes are honored in both; previously literals produced map values). FirestoreBlob fields now write proper bytes values (type-owned codec) instead of map values.
- Timestamp/GeoPoint codecs are type-owned only - their redundant scope registrations were removed (OQ1); the bytes envelope codec stays registered because byte[] cannot declare its own converter.
v1.0.1-preview.21
- No functional changes; synchronized with the framework-free MAUI integration sweep.
v1.0.1-preview.20
- Synchronized package version with the preview.20 release.
v1.0.1-preview.19
- Synchronized package version with the preview.19 release.
v1.0.1-preview.18
- Synchronized package version with the preview.18 release.
v1.0.1-preview.17
- Synchronized package version with the preview.17 release.
v1.0.1-preview.16
- Synchronized package version with the preview.16 release.
v1.0.1-preview.15
- Synchronized package version with the preview.15 release.
v1.0.1-preview.14
- Synchronized package version with the preview.14 release.
v1.0.1-preview.13
- Added offline-first optimistic writes (opt-in via FirestoreBuilder.OptimisticWrites). Writes apply locally immediately, queue in a per-user mutation queue, and flush to the server over a persistent bidirectional Write stream with resumable stream tokens. Listeners reflect pending writes via merged-view computation (server snapshot + overlays). WaitForPendingWritesAsync resolves when all queued mutations are acknowledged.
- Added ILocalStoreMutationQueue and ILocalStoreOverlayCache public capability contracts (detected by interface presence) for persisting pending mutation batches and per-document overlays.
- Added OptimisticWriteCoordinator, WritePipeline, PersistentWriteStream, and LimboResolver internal components implementing the decoupled offline-first write model without a monolithic SyncEngine.
- Added field transform overlay semantics: ServerTimestamp, Increment, ArrayUnion, ArrayRemove, field Delete, and Vector apply optimistically to the local view and are never double-applied after reconnection.
- Added Transaction.GetAsync merged-view reads when optimistic writes are enabled (transactions see the user's own pending writes).
- Eliminated the proto-to-JSON-to-Dictionary-to-T round-trip on the server read path: ProtoValueJsonWriter bridges proto MapField<string,Value> directly to Utf8JsonWriter tokens for System.Text.Json, with no intermediate Dictionary or string allocation.
- Eliminated the T-to-string-to-Dictionary-to-proto round-trip on the write path: ProtoValueJsonReader bridges Utf8JsonReader tokens directly to proto MapField<string,Value>, with no intermediate string allocation.
- Added ObjectJsonConverter so object? properties receive CLR primitives (string, long, double, bool, List<object?>, Dictionary<string,object?>) instead of JsonElement on both read and write round-trips.
- Fixed fire-and-forget exception swallowing and ordering violation in the Write stream response path: PersistentWriteStream events changed from Action to Func<...,Task> and are now awaited by the receive loop, preserving ordered ack processing and propagating exceptions.
v1.0.1-preview.12
- Fixed ObjectDisposedException on SemaphoreSlim.Release() during network disable. A race between DisableNetworkAsync and the fire-and-forget watch-stream receive loop allowed the stream to be restarted on a disposed PersistentListenStream after _gate had been disposed. RemoteStore now atomically guards ShouldStartWatchStream with _networkEnabled, and the PersistentListenStream start path detects disposed state before acquiring the gate.
- Fixed UnobservedTaskException caused by OperationCanceledException escaping the WebChannel receive loop during concurrent disposal. The receive loop now catches JSException wrapping OperationCanceledException (surfaced by .NET 10 WASM fetch abort), and HandleStreamErrorAsync is defensive against ObjectDisposedException when CloseInternalAsync races with DisposeAsync.
v1.0.1-preview.11
- Synchronized package version with the preview.11 release.
v1.0.1-preview.10
- Fixed "Cursor has too many values" (HTTP 400 INVALID_ARGUMENT) error on server queries using snapshot cursors (StartAt/StartAfter/EndAt/EndBefore with IDocumentSnapshot). Query.BuildStructuredQuery now emits normalized order-bys (explicit + implicit inequality fields + __name__ last) and serializes __name__ cursor values as ReferenceValue instead of plain string.
- Added QueryNormalizer helper centralizing the normalized order-by algorithm shared by server and local cache query paths.
- Added field-cursor validation: StartAt/StartAfter/EndAt/EndBefore(params object[]) now throw FirestoreException(InvalidArgument) when values exceed the explicit orderBy count.
- Refactored LocalQueryEvaluator to reuse QueryNormalizer, removing duplicated normalization logic.
v1.0.1-preview.9
- Fixed Timestamp to register a default JsonConverter via [JsonConverter(typeof(TimestampJsonConverter))], so System.Text.Json serialization works without an explicit user-supplied converter.
- Fixed TimestampJsonConverter.Read to handle both Firestore wire-format fields (_seconds/_nanoseconds) and the FireForNet serialized format (seconds/nanoseconds), ensuring round-trip deserialization from emulator and production responses.
v1.0.1-preview.8
- Added FirestoreErrorCode.LocalCacheFull (104) for client-side persistence cache-at-capacity errors.
- FirestoreException now extends FirebaseCoreException<FirestoreErrorCode>; MapToCoreCode deleted.
- ExceptionHelper.MapToFirestoreException is now one-way only (no reverse round-trip).
v1.0.1-preview.7
- Synchronized package version with the preview.7 release.
v1.0.1-preview.6
- Synchronized package version with the preview.6 release.
v1.0.1-preview.5
- Synchronized package version with the preview.5 release.
v1.0.1-preview.4
- Synchronized package version with the preview.4 release.
v1.0.1-preview.3
- Synchronized package version with the preview.3 release.
v1.0.1-preview.2
- Synchronized package version with the preview.2 release.
v1.0.1-preview.1
- Synchronized package version with the preview10 release.
v1.0.0-preview9
- Synchronized package version with the preview9 browser-interop-migration release.
v1.0.0-preview8
- Promoted FieldIndexValueEncoder and FieldPathHelper to public Firestore API so persistence backends share identical field-index encoding without internal-visibility coupling.
- Renamed ILocalStoreIndexManagement.DeleteIndexAsync to RemoveIndexAsync.
- Firestore now throws FirestoreErrorCode.FailedPrecondition when persistence is enabled with a cache size limit but the active local store does not implement ILocalStoreCacheManagement.
- Hardened InMemoryLocalStore multi-document ApplyChangesAsync atomicity under a single lock so concurrent reads never observe a partially applied batch.
v1.0.0-preview7
- Reworked local cache architecture with plan-based candidate retrieval through LocalQueryPlan, LocalQueryExecutor, and LocalQueryPlanner.
- Replaced broad ILocalStore.QueryAsync contract with QueryCandidatesAsync so stores return safe candidate supersets and Core Firestore remains the semantic authority.
- Added SQLite equality pushdown for supported scalar fields as a proven candidate-reduction path with mandatory final LocalQueryEvaluator execution.
- Collection path, collection group, and document path narrowing with broad-scan fallback across all stores.
v1.0.0-preview6
- Improved local cache query evaluation for cursor bounds, snapshot cursor document-name tie-breakers, and special numeric values.
v1.0.0-preview5
- Fixed Blazor WebAssembly startup crash when IFirestore is resolved early by flowing Google.Protobuf as a runtime package dependency while keeping its compile assets private to Firestore.
v1.0.0-preview4
- Synchronized package version with the preview4 release.
v1.0.0-preview3
- Synchronized package version with the preview3 release.
v1.0.0-preview2
- Initial v1.0.0-preview2 package.