Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/vale/config/vocabularies/PowerSync/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,7 @@ Zod

# Package names
drift_sqlite_async
PWAs
XCFramework
growable
ps_crud
99 changes: 53 additions & 46 deletions client-sdks/reference/capacitor.mdx

Large diffs are not rendered by default.

68 changes: 39 additions & 29 deletions client-sdks/reference/dotnet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import SdkFeatures from '/snippets/sdk-features.mdx';
import DotNetInstallation from '/snippets/dotnet/installation.mdx';
import DotNetWatch from '/snippets/dotnet/basic-watch-query.mdx';
import GenerateSchemaAutomatically from '/snippets/generate-schema-automatically.mdx';
import SdkClientSideSchema from '/snippets/sdk-client-side-schema.mdx';
import LocalOnly from '/snippets/local-only-escape.mdx';
import SubscribeSyncStreamsIntro from '/snippets/subscribe-sync-streams-intro.mdx';
import SubscribeSyncStreamsOutro from '/snippets/subscribe-sync-streams-outro.mdx';
import DotnetSubscribeSyncStream from '/snippets/dotnet/subscribe-sync-stream.mdx';

```text Build with AI icon="sparkles" wrap
Install the PowerSync Agent Skills with: npx skills add powersync-ja/agent-skills. Then follow the skills to onboard this project to PowerSync using the .NET SDK.
Expand Down Expand Up @@ -37,7 +41,7 @@ Install the PowerSync Agent Skills with: npx skills add powersync-ja/agent-skill
</CardGroup>

<Note>
This SDK is currently in a [**beta** release](/resources/feature-status). It is production-ready for tested use cases. APIs are stable and breaking changes will be communicated clearly.
This SDK is currently in a [**beta** release](/resources/feature-status). It is production-ready for tested use cases. APIs are stable, and we communicate breaking changes clearly.
</Note>

## Supported Frameworks and Targets
Expand All @@ -46,15 +50,15 @@ The PowerSync .NET SDK supports:

* **.NET Versions**: 6, 8, and 9
* **.NET Standard**: 2.0 (for compatibility with older libraries and frameworks)
* **.NET Framework**: Version 4.8 (requires additional configuration see the package [README](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file))
* **.NET Framework**: Version 4.8, which requires additional configuration (see the package [README](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file))
* **MAUI**: Cross-platform support for Android, iOS, Mac Catalyst, and Windows (targeting `net8.0` and `net9.0` mobile frameworks)
* **WPF**: Windows desktop applications
* **Console/CLI**: Windows (x64, ARM), macOS (x64, ARM), and Linux (x64, ARM)

**Current Limitations**:
**Current limitations:**
* Blazor (web) platforms are not yet supported.

For more details, please refer to the package [README](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file).
For more details, see the package [README](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file).

## SDK Features

Expand All @@ -64,25 +68,23 @@ For more details, please refer to the package [README](https://github.com/powers

<DotNetInstallation />

**Prerequisites**: To sync data between your client-side app and your backend source database, you must have completed the necessary setup for PowerSync, which includes connecting your source database to the PowerSync Service and deploying Sync Streams (or legacy Sync Rules) (steps 1-4 in the [Setup Guide](/intro/setup-guide)).
**Prerequisites:** Before you start, connect your source database to the PowerSync Service and deploy Sync Streams. These are steps 1-4 in the [Setup Guide](/intro/setup-guide).

### 1. Define the Client-Side Schema

import SdkClientSideSchema from '/snippets/sdk-client-side-schema.mdx';

<SdkClientSideSchema />

<GenerateSchemaAutomatically />

You can use [this example](https://github.com/powersync-ja/powersync-dotnet/blob/main/demos/CommandLine/AppSchema.cs) as a reference when defining your schema.

The types available are `text`, `integer` and `real`. These should map directly to the values produced by your [Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)). If a value doesn't match, it is cast automatically. For details on how backend source database types are mapped to the SQLite types, see [Types](/sync/types).
The available column types are `text`, `integer`, and `real`. These should match the values produced by your Sync Streams. If a value does not match, it is cast automatically. For details on how source database types map to SQLite types, see [Types](/sync/types).

#### Schema Definition Syntax

There are two supported syntaxes for defining the schema:

**Attribute-based (recommended)** — Annotate a C# class with [`[Table]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.TableAttribute.html), [`[Column]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.ColumnAttribute.html), and [`[Index]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.IndexAttribute.html) attributes. The same class can then be used directly as the result type in queries, so you define your data structure once:
**Attribute-based (recommended):** Annotate a C# class with [`[Table]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.TableAttribute.html), [`[Column]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.ColumnAttribute.html), and [`[Index]`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.DB.Schema.Attributes.IndexAttribute.html) attributes. The same class can then be used directly as the result type in queries, so you define your data structure once:

```cs
using PowerSync.Common.DB.Schema;
Expand Down Expand Up @@ -146,9 +148,9 @@ var todos = await db.GetAll<Todo>("SELECT * FROM todos");

### 2. Instantiate the PowerSync Database

Next, you need to instantiate the PowerSync database. PowerSync streams changes from your backend source database into the client-side SQLite database, based on your [Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)). In your client-side app, you can read from and write to the local SQLite database, whether the user is online or offline.
Next, instantiate the PowerSync database. PowerSync streams changes from your backend source database into the client-side SQLite database, based on your Sync Streams. Your app reads from and writes to this local database whether the user is online or offline.

**Example**:
**Example:**

The initialization syntax differs slightly between the Common and MAUI SDKs:

Expand Down Expand Up @@ -188,7 +190,7 @@ The initialization syntax differs slightly between the Common and MAUI SDKs:
DbFilename = dbPath
});

var Db = new PowerSyncDatabase(new PowerSyncDatabaseOptions()
var db = new PowerSyncDatabase(new PowerSyncDatabaseOptions()
{
Database = factory, // Supply a factory
Schema = AppSchema.PowerSyncSchema,
Expand All @@ -203,17 +205,17 @@ The initialization syntax differs slightly between the Common and MAUI SDKs:

### 3. Integrate with Your Backend

The PowerSync backend connector provides the connection between your application backend and the PowerSync client-side managed SQLite database. It is used to:
The backend connector connects the PowerSync client SDK to your application backend. The SDK uses it to:

1. Retrieve an auth token to connect to the PowerSync instance.
2. Upload client-side writes to your backend API. Any writes that are made to the SQLite database are placed into an upload queue by the PowerSync Client SDK and automatically uploaded to your app backend (where you apply those changes to the backend source database) when the user is connected.
1. Get an auth token to connect to the PowerSync instance.
2. Upload client-side writes to your backend API. The SDK places every write to the SQLite database in an upload queue and uploads the queue to your backend when the user is connected. Your backend then applies the changes to the source database.

Accordingly, the connector must implement two methods:
The connector must implement two methods:

1. [IPowerSyncBackendConnector.FetchCredentials](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.Connection.IPowerSyncBackendConnector.FetchCredentials.html) - This method is automatically invoked by the PowerSync Client SDK to obtain authentication credentials. The SDK caches credentials internally and only calls this method when needed (e.g. on initial connection or when the token is near expiry). See [When `fetchCredentials()` is Called](/configuration/app-backend/client-side-integration#when-fetchcredentials-is-called) for details, and [Authentication Setup](/configuration/auth/overview) for instructions on how the credentials should be generated.
2. [IPowerSyncBackendConnector.UploadData](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.Connection.IPowerSyncBackendConnector.UploadData.html) - This method will be automatically invoked by the PowerSync Client SDK whenever it needs to upload client-side writes to your app's backend API. You need to implement how those writes are processed and uploaded in this method. See [When `uploadData()` is Called](/configuration/app-backend/client-side-integration#when-uploaddata-is-called) for details on triggers, throttling, and retry behavior, and [Writing Client Changes](/handling-writes/writing-client-changes) for considerations on the app backend implementation.
1. [IPowerSyncBackendConnector.FetchCredentials](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.Connection.IPowerSyncBackendConnector.FetchCredentials.html) - The SDK calls this method to get authentication credentials. It caches the credentials and calls the method again only when needed, for example on the first connection or when the token is near expiry. See [When `fetchCredentials()` is Called](/configuration/app-backend/client-side-integration#when-fetchcredentials-is-called) for details and [Authentication Setup](/configuration/auth/overview) for how to generate credentials.
2. [IPowerSyncBackendConnector.UploadData](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.Connection.IPowerSyncBackendConnector.UploadData.html) - The SDK calls this method whenever it has client-side writes to upload to your backend API. Implement how those writes are processed and uploaded. See [When `uploadData()` is Called](/configuration/app-backend/client-side-integration#when-uploaddata-is-called) for triggers, throttling, and retry behavior, and [Writing Client Changes](/handling-writes/writing-client-changes) for the app backend implementation.

**Example**:
**Example:**

```cs
using System;
Expand Down Expand Up @@ -246,7 +248,7 @@ public class MyConnector : IPowerSyncBackendConnector
UserId = "user-123";

// Configure your service endpoints
_backendUrl = "https://your-backend-api.example.com";
_backendUrl = "[Your backend API URL]";
_powerSyncUrl = "https://your-powersync-instance.powersync.journeyapps.com";
}

Expand Down Expand Up @@ -335,16 +337,24 @@ await db.WaitForFirstSync(); // Optional, to wait for a complete snapshot of dat

<LocalOnly />

## Using PowerSync: CRUD functions
### 4. Subscribe to Sync Streams

<SubscribeSyncStreamsIntro />

<DotnetSubscribeSyncStream />

<SubscribeSyncStreamsOutro />

## Using PowerSync: CRUD Functions

Once the PowerSync instance is configured you can start using the SQLite DB functions.
Once the PowerSync database is connected and your streams have synced, the data is in the local SQLite database.

The most commonly used CRUD functions to interact with your SQLite data are:

- [`PowerSyncDatabase.Get`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Get.html) - get (SELECT) a single row from a table.
- [`PowerSyncDatabase.GetAll`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.GetAll.html) - get (SELECT) a set of rows from a table.
- [`PowerSyncDatabase.Watch`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Watch.html) - execute a read query every time source tables are modified.
- [`PowerSyncDatabase.Execute`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Execute.html) - execute a write (INSERT/UPDATE/DELETE) query.
- [`PowerSyncDatabase.Get`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Get.html) - get (`SELECT`) a single row from a table.
- [`PowerSyncDatabase.GetAll`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.GetAll.html) - get (`SELECT`) a set of rows from a table.
- [`PowerSyncDatabase.Watch`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Watch.html) - execute a read query every time a dependent table changes.
- [`PowerSyncDatabase.Execute`](https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.Common.Client.PowerSyncDatabase.Execute.html) - execute a write (`INSERT`/`UPDATE`/`DELETE`) query.

### Fetching a Single Item

Expand Down Expand Up @@ -381,14 +391,14 @@ The `Execute` method can be used for executing single SQLite write statements.
```cs
// And db.Execute for inserts, updates and deletes:
await db.Execute(
"insert into lists (id, name, owner_id, created_at) values (uuid(), 'New User', ?, datetime())",
"INSERT INTO lists (id, name, owner_id, created_at) VALUES (uuid(), 'New list', ?, datetime())",
[connector.UserId]
);
```

## Configure Logging

Enable logging to help you debug your app. By default, the SDK uses a no-op logger that doesn't output any logs. To enable logging, you can configure a custom logger using .NET's `ILogger` interface:
By default, the SDK uses a no-op logger that outputs nothing. To enable logging, configure a logger with .NET's `ILogger` interface:

```cs
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -425,7 +435,7 @@ See [Supported Platforms -> .NET SDK](/resources/supported-platforms#net).

## Upgrading the SDK

To upgrade to the latest version of the PowerSync package, run the below command in your project folder:
To upgrade the PowerSync package, run the following command in your project folder:

<Tabs>
<Tab title="Common">
Expand Down
Loading
Loading