Skip to content

Commit ee7b375

Browse files
benitavChriztiaan
andauthored
.Net alpha (#148)
* .Net alpha * Update client-sdk-references/dotnet.mdx * spacing --------- Co-authored-by: Christiaan Landman <chriz.ek@gmail.com>
1 parent 55223cb commit ee7b375

File tree

7 files changed

+299
-16
lines changed

7 files changed

+299
-16
lines changed

client-sdk-references/dotnet.mdx

Lines changed: 287 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,292 @@
11
---
2-
title: ".NET (closed alpha)"
2+
title: ".NET (alpha)"
33
description: "SDK reference for using PowerSync in .NET clients."
44
sidebarTitle: Overview
55
---
66

7-
<Note>
8-
Our .NET client SDK is currently in a closed alpha release for early testing with select customers. You can explore the repo [here](https://github.com/powersync-ja/powersync-dotnet), however it is not yet officially published so expect breaking changes and instability as development continues.
9-
</Note>
7+
<CardGroup>
8+
<Card title="PowerSync SDK on NuGet" icon="nuget" href="https://www.nuget.org/packages/PowerSync.Common/">
9+
This SDK is distributed via NuGet [\[External link\].](https://www.nuget.org/packages/PowerSync.Common/)
10+
</Card>
11+
12+
<Card title="Source Code" icon="github" href="https://github.com/powersync-ja/powersync-dotnet">
13+
Refer to the powersync-dotnet repo on GitHub.
14+
</Card>
15+
16+
<Card title="API Reference (Coming soon)" icon="book">
17+
A full API Reference for this SDK is not yet available. This is planned for a future release.
18+
</Card>
19+
20+
<Card title="Example App" icon="code" href="https://github.com/powersync-ja/powersync-dotnet/tree/main/demos/CommandLine">
21+
A small CLI app showcasing bidirectional sync.
22+
</Card>
23+
</CardGroup>
24+
25+
## Supported Frameworks and Targets
26+
27+
The PowerSync .NET SDK supports:
28+
29+
* **.NET Versions**: 6, 8, and 9
30+
* **.NET Framework**: Version 4.8 (requires additional configuration)
31+
32+
**Current Limitations**:
33+
* The SDK in its current state is designed for desktop, server, and traditional binary applications.
34+
* Web and mobile platforms (Blazor, MAUI) are not yet supported, but are planned.
35+
36+
For more details, please refer to the package [Readme](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file#supported-frameworks).
37+
38+
## SDK Features
39+
40+
* Provides real-time streaming of database changes.
41+
* Offers direct access to the SQLite database, enabling the use of SQL on both client and server sides.
42+
* Enables subscription to queries for receiving live updates.
43+
* Eliminates the need for client-side database migrations as these are managed automatically.
44+
45+
## Quickstart
46+
47+
To start using PowerSync in a .NET client, install the package:
48+
49+
```bash
50+
dotnet add package PowerSync.Common --prerelease
51+
```
52+
53+
<Info>
54+
Add `--prerelease` while this package is in alpha.
55+
</Info>
56+
57+
Next, make sure that you have:
58+
59+
* Signed up for a PowerSync Cloud account ([here](https://accounts.journeyapps.com/portal/powersync-signup?s=docs)) or [self-host PowerSync](/self-hosting/getting-started).
60+
* [Configured your backend database](/installation/database-setup) and connected it to your PowerSync instance.
61+
62+
### 1. Define the schema
63+
64+
The first step is defining the schema for the local SQLite database.
65+
66+
This schema represents a "view" of the downloaded data. No migrations are required — the schema is applied directly when the local PowerSync database is constructed (as we'll show in the next step).
67+
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.
68+
69+
### 2. Instantiate the PowerSync Database
70+
71+
Next, you need to instantiate the PowerSync database — this is the core managed database.
72+
73+
Its primary functions are to record all changes in the local database, whether online or offline. In addition, it automatically uploads changes to your app backend when connected.
74+
75+
**Example**:
76+
77+
```cs
78+
using PowerSync.Common.Client;
79+
80+
class Demo
81+
{
82+
static async Task Main()
83+
{
84+
var db = new PowerSyncDatabase(new PowerSyncDatabaseOptions
85+
{
86+
Database = new SQLOpenOptions { DbFilename = "tododemo.db" },
87+
Schema = AppSchema.PowerSyncSchema,
88+
});
89+
await db.Init();
90+
}
91+
}
92+
```
93+
94+
### 3. Integrate with your Backend
95+
96+
The PowerSync backend connector provides the connection between your application backend and the PowerSync client-side managed SQLite database.
97+
98+
It is used to:
99+
100+
1. Retrieve an auth token to connect to the PowerSync instance.
101+
2. Apply local changes on your backend application server (and from there, to Postgres)
102+
103+
Accordingly, the connector must implement two methods:
104+
105+
1. [PowerSyncBackendConnector.FetchCredentials](https://github.com/powersync-ja/powersync-dotnet/blob/main/demos/CommandLine/NodeConnector.cs#L50) - This is called every couple of minutes and is used to obtain credentials for your app backend API. -> See [Authentication Setup](/installation/authentication-setup) for instructions on how the credentials should be generated.
106+
2. [PowerSyncBackendConnector.UploadData](https://github.com/powersync-ja/powersync-dotnet/blob/main/demos/CommandLine/NodeConnector.cs#L72) - Use this to upload client-side changes to your app backend.
107+
-> See [Writing Client Changes](/installation/app-backend-setup/writing-client-changes) for considerations on the app backend implementation.
108+
109+
**Example**:
110+
111+
```cs
112+
using System;
113+
using System.Collections.Generic;
114+
using System.Net.Http;
115+
using System.Text;
116+
using System.Text.Json;
117+
using System.Threading.Tasks;
118+
using PowerSync.Common.Client;
119+
using PowerSync.Common.Client.Connection;
120+
using PowerSync.Common.DB.Crud;
121+
122+
public class MyConnector : IPowerSyncBackendConnector
123+
{
124+
private readonly HttpClient _httpClient;
125+
126+
// User credentials for the current session
127+
public string UserId { get; private set; }
128+
129+
// Service endpoints
130+
private readonly string _backendUrl;
131+
private readonly string _powerSyncUrl;
132+
private string? _clientId;
133+
134+
public MyConnector()
135+
{
136+
_httpClient = new HttpClient();
137+
138+
// In a real app, this would come from your authentication system
139+
UserId = "user-123";
140+
141+
// Configure your service endpoints
142+
_backendUrl = "https://your-backend-api.example.com";
143+
_powerSyncUrl = "https://your-powersync-instance.powersync.journeyapps.com";
144+
}
145+
146+
public async Task<PowerSyncCredentials?> FetchCredentials()
147+
{
148+
try {
149+
// Obtain a JWT from your authentication service.
150+
// See https://docs.powersync.com/installation/authentication-setup
151+
// If you're using Supabase or Firebase, you can re-use the JWT from those clients, see
152+
// - https://docs.powersync.com/installation/authentication-setup/supabase-auth
153+
// - https://docs.powersync.com/installation/authentication-setup/firebase-auth
154+
155+
var authToken = "your-auth-token"; // Use a development token (see Authentication Setup https://docs.powersync.com/installation/authentication-setup/development-tokens) to get up and running quickly
156+
157+
// Return credentials with PowerSync endpoint and JWT token
158+
return new PowerSyncCredentials(_powerSyncUrl, authToken);
159+
160+
}
161+
catch (Exception ex)
162+
{
163+
Console.WriteLine($"Error fetching credentials: {ex.Message}");
164+
throw;
165+
}
166+
}
167+
168+
public async Task UploadData(IPowerSyncDatabase database)
169+
{
170+
// Get the next transaction to upload
171+
CrudTransaction? transaction;
172+
try
173+
{
174+
transaction = await database.GetNextCrudTransaction();
175+
}
176+
catch (Exception ex)
177+
{
178+
Console.WriteLine($"UploadData Error: {ex.Message}");
179+
return;
180+
}
181+
182+
// If there's no transaction, there's nothing to upload
183+
if (transaction == null)
184+
{
185+
return;
186+
}
187+
188+
// Get client ID if not already retrieved
189+
_clientId ??= await database.GetClientId();
190+
191+
try
192+
{
193+
// Convert PowerSync operations to your backend format
194+
var batch = new List<object>();
195+
foreach (var operation in transaction.Crud)
196+
{
197+
batch.Add(new
198+
{
199+
op = operation.Op.ToString(), // INSERT, UPDATE, DELETE
200+
table = operation.Table,
201+
id = operation.Id,
202+
data = operation.OpData
203+
});
204+
}
205+
206+
// Send the operations to your backend
207+
var payload = JsonSerializer.Serialize(new { batch });
208+
var content = new StringContent(payload, Encoding.UTF8, "application/json");
209+
210+
HttpResponseMessage response = await _httpClient.PostAsync($"{_backendUrl}/api/data", content);
211+
response.EnsureSuccessStatusCode();
212+
213+
// Mark the transaction as completed
214+
await transaction.Complete();
215+
}
216+
catch (Exception ex)
217+
{
218+
Console.WriteLine($"UploadData Error: {ex.Message}");
219+
throw;
220+
}
221+
}
222+
}
223+
```
224+
225+
With your database instantiated and your connector ready, call `connect` to start the synchronization process:
226+
227+
```cs
228+
await db.Connect(new MyConnector());
229+
await db.WaitForFirstSync(); // Optional, to wait for a complete snapshot of data to be available
230+
```
231+
232+
## Usage
233+
234+
After connecting the client database, it is ready to be used. You can run queries and make updates as follows:
235+
236+
```cs
237+
// Use db.Get() to fetch a single row:
238+
Console.WriteLine(await db.Get<object>("SELECT powersync_rs_version();"));
239+
240+
// Or db.GetAll() to fetch all:
241+
// Where List result is defined:
242+
// record ListResult(string id, string name, string owner_id, string created_at);
243+
Console.WriteLine(await db.GetAll<ListResult>("SELECT * FROM lists;"));
244+
245+
// Use db.Watch() to watch queries for changes (await is used to wait for initialization):
246+
await db.Watch("select * from lists", null, new WatchHandler<ListResult>
247+
{
248+
OnResult = (results) =>
249+
{
250+
Console.WriteLine("Results: ");
251+
foreach (var result in results)
252+
{
253+
Console.WriteLine(result.id + ":" + result.name);
254+
}
255+
},
256+
OnError = (error) =>
257+
{
258+
Console.WriteLine("Error: " + error.Message);
259+
}
260+
});
261+
262+
// And db.Execute for inserts, updates and deletes:
263+
await db.Execute(
264+
"insert into lists (id, name, owner_id, created_at) values (uuid(), 'New User', ?, datetime())",
265+
[connector.UserId]
266+
);
267+
```
268+
269+
## Logging
270+
271+
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:
272+
273+
```cs
274+
using Microsoft.Extensions.Logging;
275+
using PowerSync.Common.Client;
276+
277+
// Create a logger factory
278+
ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
279+
{
280+
builder.AddConsole(); // Enable console logging
281+
builder.SetMinimumLevel(LogLevel.Information); // Set minimum log level
282+
});
283+
284+
var logger = loggerFactory.CreateLogger("PowerSyncLogger");
285+
286+
var db = new PowerSyncDatabase(new PowerSyncDatabaseOptions
287+
{
288+
Database = new SQLOpenOptions { DbFilename = "powersync.db" },
289+
Schema = AppSchema.PowerSyncSchema,
290+
Logger = logger
291+
});
292+
```

client-sdk-references/node.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ After connecting the client database, it is ready to be used. The API to run que
172172
// Use db.get() to fetch a single row:
173173
console.log(await db.get('SELECT powersync_rs_version();'));
174174

175-
// Or db.all() to fetch all:
176-
console.log(await db.all('SELECT * FROM lists;'));
175+
// Or db.getAll() to fetch all:
176+
console.log(await db.getAll('SELECT * FROM lists;'));
177177

178178
// Use db.watch() to watch queries for changes:
179179
const watchLists = async () => {

installation/client-side-setup.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The next step after configuring your database and connecting it to your PowerSyn
1818

1919
2. Write mutations to your backend
2020

21-
PowerSync currently supports apps built in [Flutter](/client-sdk-references/flutter), [React Native & Expo](/client-sdk-references/react-native-and-expo), [JavaScript Web](/client-sdk-references/javascript-web), [Node.js](/client-sdk-references/node) (alpha), [Kotlin Multiplatform](/client-sdk-references/kotlin-multiplatform) (beta), [Swift](/client-sdk-references/swift) (beta), and [.NET](/client-sdk-references/dotnet) (closed alpha).
21+
PowerSync currently supports apps built in [Flutter](/client-sdk-references/flutter), [React Native & Expo](/client-sdk-references/react-native-and-expo), [JavaScript Web](/client-sdk-references/javascript-web), [Node.js](/client-sdk-references/node) (alpha), [Kotlin Multiplatform](/client-sdk-references/kotlin-multiplatform) (beta), [Swift](/client-sdk-references/swift) (beta), and [.NET](/client-sdk-references/dotnet) (alpha).
2222

2323
Please see the steps based on your app framework:
2424

installation/quickstart-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ PowerSync is designed to be stack agnostic, and currently supports **Postgres**,
1010
- [**Node.js**](/client-sdk-references/node) (alpha)
1111
- [**Kotlin Multiplatform**](/client-sdk-references/kotlin-multiplatform) (beta)
1212
- [**Swift**](/client-sdk-references/swift) (beta)
13-
- [**.NET**](/client-sdk-references/dotnet) (closed alpha)
13+
- [**.NET**](/client-sdk-references/dotnet) (alpha)
1414

1515
<Note>
1616
Support for additional platforms is on our [Roadmap](https://roadmap.powersync.com/). If one isn't supported today, please add your vote and check back soon.

migration-guides/mongodb-atlas.mdx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ Here is an example of a client-side schema for PowerSync using a simple `todos`
254254
```
255255

256256
```typescript .NET (Coming soon)
257-
// Our .NET SDK is currently in a closed alpha release.
257+
// Our .NET SDK is currently in an alpha release.
258258
259259
```
260260

@@ -383,7 +383,7 @@ Now that we have our Sync Rules and client-side schema defined, we can instantia
383383
```
384384

385385
```typescript .NET (Coming soon)
386-
// Our .NET SDK is currently in a closed alpha release.
386+
387387
388388
```
389389

@@ -439,8 +439,7 @@ Reading data in the application which uses PowerSync is very simple: we use SQLi
439439
```
440440

441441
```typescript .NET (Coming soon)
442-
// Our .NET SDK is currently in a closed alpha release.
443-
442+
444443
```
445444

446445
</CodeGroup>
@@ -487,7 +486,7 @@ The same applies to writing data: `INSERT`, `UPDATE` and `DELETE` statements are
487486
```
488487

489488
```typescript .NET (Coming soon)
490-
// Our .NET SDK is currently in a closed alpha release.
489+
491490
492491
```
493492

resources/demo-apps-example-projects.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ Example projects are listed under backend they use, but you can easily wire up y
9393

9494
</Accordion>
9595

96-
<Accordion title=".NET (closed alpha)" icon="wave-sine">
97-
#### Coming soon!
96+
<Accordion title=".NET (alpha)" icon="wave-sine">
97+
#### Self-Hosted:
98+
* [CLI example](https://github.com/powersync-ja/powersync-dotnet/tree/main/demos/CommandLine)
9899
</Accordion>
99100

100101
<Accordion title="Custom Backend Examples" icon="screwdriver-wrench">

snippets/client-sdks.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
</Card>
1919

2020
<Card title=".NET" icon="wave-sine" href="/client-sdk-references/dotnet">
21-
Currently in a closed alpha release.
21+
Currently in an alpha release.
2222
</Card>
2323
</CardGroup>

0 commit comments

Comments
 (0)