Przejdź do treści
Biblioteka skilli
Programowanie · Budowanie i kod

csharp-client

/csharp-client

Dostarcza materiał referencyjny klienta SpacetimeDB w C#/.NET dla aplikacji konsolowych i desktopowych.

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

  1. Connection
  2. Automatic Reconnect and Token Refresh
  3. Event Loop (Critical)
  4. Subscriptions
  5. Submodule Accessors and View Arguments
  6. Row Callbacks
  7. Reading the Client Cache
  8. Calling Reducers
  9. Reducer Callbacks
  10. 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

RepozytoriumWynikLicencja
Ta strona · clockworklabs/spacetimedb95AGPL-3.0
clockworklabs/spacetimedb95AGPL-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.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.