Programowanie · Budowanie i kod
csharp-client
/csharp-client
Dostarcza materiał referencyjny klienta SpacetimeDB w C#/.NET dla aplikacji konsolowych i desktopowych.
Dla kogo
- Autor
- clockworklabs ↗
- Repozytorium
- spacetimedb ↗
- Licencja
- AGPL-3.0
- Ostatnia zmiana repozytorium
- 12.11.2026
Ocena i bezpieczeństwo
95/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść30 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
- Pliki w paczce
- 1
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 1
Przestarzałość
Brak sygnałów. Repozytorium zmienione 12.11.2026, bez odwołań do wycofanych modeli i API.
Licencja
AGPL-3.0, copyleft: przeróbki udostępniane innym muszą mieć tę samą licencję.
Co robi i kiedy
Dostarcza materiał referencyjny klienta SpacetimeDB w C#/.NET dla aplikacji konsolowych i desktopowych.
Oryginalny opis (EN)
SpacetimeDB C#/.NET client SDK reference. Use when building C# clients that connect to SpacetimeDB (console, desktop, or any .NET app).
Jak działa
- Connection
- Automatic Reconnect and Token Refresh
- Event Loop (Critical)
- Subscriptions
- Submodule Accessors and View Arguments
- Row Callbacks
- Reading the Client Cache
- Calling Reducers
- Reducer Callbacks
- Identity
Sekcje z nagłówków SKILL.md, w oryginale · 196 linii, 930 słów
Podgląd SKILL.md
---
name: csharp-client
description: SpacetimeDB C#/.NET client SDK reference. Use when building C# clients that connect to SpacetimeDB (console, desktop, or any .NET app).
license: Apache-2.0
metadata:
author: clockworklabs
version: "2.0"
role: client
language: csharp
cursor_globs: "**/*.cs"
cursor_always_apply: true
---
# SpacetimeDB C# Client
Install: `dotnet add package SpacetimeDB.ClientSDK`
Generated bindings convert snake_case names to PascalCase, including row fields: a server column `trip_id` is `TripId` on client rows.
## Connection
```csharp
using SpacetimeDB;
using SpacetimeDB.Types;
var conn = DbConnection.Builder()
.WithUri("http://localhost:3000")
.WithDatabaseName("my-database")
.WithToken(savedToken)
.WithCompression(Compression.Brotli) // optional; this is the default
.OnConnect((conn, identity, token) =>
{
Console.WriteLine($"Connected as: {identity}");
// Save token for reconnection
File.WriteAllText("auth_token.txt", token);
conn.SubscriptionBuilder()
.OnApplied(OnSubscriptionApplied)
.SubscribeToAllTables();
})
.OnConnectError(err => Console.Error.WriteLine($"Connection failed: {err}"))
.OnDisconnect((conn, err) =>
{
if (err != null) Console.Error.WriteLine($"Disconnected: {err}");
})
.Build();
```
Compression options are `Compression.Brotli`, `Compression.Gzip`, and `Compression.None`. The SDK uses Brotli when `WithCompression` is omitted.
## Automatic Reconnect and Token Refresh
Automatic reconnect is opt-in: add `.WithAutomaticReconnect()` to the builder. Initial connection failures do not retry. After an established connection is lost, the SDK retries with exponential backoff and jitter from `MinDelay` (default 1 s) up to `MaxDelay` (default 30 s); tune them with `.WithAutomaticReconnect(new AutomaticReconnectOptions { MinDelay = ..., MaxDelay = ... })`. Values below the 500 ms and 1 s floors are raised with a warning, so that retrying clients cannot overwhelm the database. `Disconnect()` permanently stops recovery.
Keep calling `FrameTick()` while `IsActive` is false. `IsReconnecting` is true while recovering before the next handshake. Use `.OnDisconnect((conn, error, next) => ...)` and `.OnConnectError((error, next) => ...)` to inspect `NextReconnect?`: a non-null value provides `Attempt` and `Delay`; null means no retry is scheduled. Existing callback overloads still work.
`OnConnect` runs on every successful reconnect, so create the subscription in the example above only on the first connection, or move it after `Build()`. Register row callbacks once as well. The same connection, identity, table handles, and subscriptions survive; each attempt gets a fresh `ConnectionId`. Cached rows stay readable but stale during outages. The SDK replays subscriptions in one batch and emits only net row changes. Subscription `OnApplied` runs again after replay; use it to mark data ready, not for repeated one-time setup.
For expiring credentials, combine `.WithToken(initialToken)` with `.WithTokenProvider(() => RefreshTokenAsync())`, where your provider returns `Task<string>` for the same identity. The provider is not called for the initial connection. Before retries, it is called when remaining validity is at most 30 seconds or 5% of the token lifetime, whichever is greater, when expiry cannot be read, or after a reused token is rejected. Provider failures retry; rejection of a freshly provided token is terminal. No periodic refresh runs while connected. Disconnecting ignores a pending provider result but does not cancel the provider's own work.
Calls made while disconnected fail immediately. Pending reducer calls receive `Status.UnknownResult`; pending procedures and one-off queries fail with `UnknownResultException`. These calls may already have executed and are never replayed. Regenerate bindings so unhandled unknown reducer outcomes reach `OnUnhandledReducerError`.
## Event Loop (Critical)
**`FrameTick()` must be called in your main loop.** The SDK queues all network messages and only processes them when you call `FrameTick()`. Without it, no callbacks fire.
```csharp
while (running)
{
conn.FrameTick();
// Your application logic...
Thread.Sleep(16); // ~60fps
}
```
**Thread safety**: `FrameTick()` processes messages on the calling thread. Do NOT call it from a background thread. Do NOT access `conn.Db` from background threads.
## Subscriptions
```csharp
// Subscribe to all tables
conn.SubscriptionBuilder()
.OnApplied(ctx => Console.WriteLine("Subscription ready"))
.SubscribeToAllTables();
// Subscribe with typed query builder (recommended)
conn.SubscriptionBuilder()
.OnApplied(OnSubscriptionApplied)
.AddQuery(q => q.From.Player().Where(p => p.Level.Gte(5u)))
.AddQuery(q => q.From.GameState())
.Subscribe();
// Or with raw SQL strings
conn.SubscriptionBuilder()
.OnApplied(OnSubscriptionApplied)
.Subscribe(new[] {
"SELECT * FROM player WHERE level >= 5",
"SELECT * FROM game_state"
});
```
## Submodule Accessors and View Arguments
A namespace accessor `MyAuth` is nested in the generated table, reducer, and procedure APIs:
```csharp
conn.SubscriptionBuilder()
.AddQuery(q => q.From.MyAuth.User())
.Subscribe();
// Rows: conn.Db.MyAuth.User
// Reducers: conn.Reducers.MyAuth.Add(10)
// Procedures: conn.Procedures.MyAuth.CountUsers((ctx, result) => { ... })
```
The query builder and calls encode canonical names automatically. Raw SQL/HTTP/CLI calls use canonical qualified names, such as `auth_data.<table>` for a namespace explicitly named `auth_data`. All namespaces share the connection and cache.
For views with arguments (2.13+), use raw SQL; C# has no typed argument-bearing view query builder yet:
```csharp
conn.SubscriptionBuilder().Subscribe(new[] { "SELECT * FROM by_id(42)" });
```
Use explicit queries for every table on that connection, not subscribe-all, which skips views with arguments. Only `SELECT * FROM view_name(literal_args)` is supported. All argument values share one cache table; unsubscribe from obsolete arguments to avoid combining their rows. Validate/encode dynamic values as SQL literals rather than concatenating untrusted input. Keep calling `FrameTick()` to process subscription updates.
## Row Callbacks
```csharp
conn.Db.Player.OnInsert += (EventContext ctx, Player player) =>
{
Console.WriteLine($"Player joined: {player.Name}");
};
conn.Db.Player.OnDelete += (EventContext ctx, Player player) =>
{
Console.WriteLine($"Player left: {player.Name}");
};
conn.Db.Player.OnUpdate += (EventContext ctx, Player oldPlayer, Player newPlayer) =>
{
Console.WriteLine($"Player updated: {newPlayer.Name}");
};
```
## Reading the Client Cache
```csharp
// Find by primary key
if (conn.Db.Player.Id.Find(playerId) is Player player)
{
Console.WriteLine($"Player: {player.Name}");
}
// Find by unique column
var me = conn.Db.Player.Identity.Find(myIdentity);
// Filter by indexed column
foreach (var p in conn.Db.Player.Level.Filter(5))
{
Console.WriteLine($"Level 5: {p.Name}");
}
// Iterate all rows
foreach (var p in conn.Db.Player.Iter())
{
Console.WriteLine(p.Name);
}
// Count
int total = conn.Db.Player.Count;
```
## Calling Reducers
```csharp
conn.Reducers.CreatePlayer("Alice");
conn.Reducers.MovePlayer(10.0f, 20.0f);
conn.Reducers.SendMessage("Hello!");
```
Reducer calls return `void`; observe failures via the reducer callbacks below (`Status.Failed`).
## Reducer Callbacks
```csharp
conn.Reducers.OnSendMessage += (ReducerEventContext ctx, string text) =>
{
if (ctx.Event.Status is Status.Committed)
Console.WriteLine($"Message sent: {text}");
else if (ctx.Event.Status is Status.Failed(var reason))
Console.Error.WriteLine($"Send failed: {reason}");
else if (ctx.Event.Status is Status.UnknownResult)
Console.Error.WriteLine("Connection lost before the result arrived; the message may have been sent.");
};
```
## Identity
```csharp
// Identities from OnConnect callback
Identity myIdentity;
// Compare identities
if (player.Owner == myIdentity) { /* it's me */ }
// Display
Console.WriteLine($"Identity: {identity}");
```
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · clockworklabs/spacetimedb | 95 | AGPL-3.0 |
| clockworklabs/spacetimedb | 95 | AGPL-3.0 |
Migawka bazy z 13.11.2026 · wersja paczki a2914ecbb713 (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 95typescript-client
Opisuje klienta SDK SpacetimeDB dla TypeScript i React, do budowy przeglądarkowych klientów połączonych z bazą. - 95typescript-client
Podaje referencję klienta SpacetimeDB w TypeScript i React przy budowie klientów webowych połączonych z bazą. - 91spacetimedb-local
Pomaga uruchamiać moduł SpacetimeDB lokalnie na własnym komputerze. - 96csharp
Podaje wytyczne budowy aplikacji w C# dla plików .cs, od struktury kodu po obsługę błędów. - 100programming-csharp
Podpowiada nowoczesne praktyki C# i .NET: kontrakty nullable, własność async, dostęp do danych i obsługę błędów. - 100csharp-dotnet-development
Pomaga budować, przeglądać, modernizować i debugować aplikacje C# i .NET, w tym ASP.NET Core, EF Core, usługi w tle, współbieżność, .NET MAUI, testy, pakowanie i integrację AI.