# Use the C# / .NET SDK

**Applies to:** current development source bundles. Obtain a matched client/server release through [early-access support](mailto:info@simplemagic.com); registry publication is not available yet. Paths below are relative to the supplied source checkout.

Blocking .NET 10 client with a P/Invoke binding to `libsmkv`. Initial source release;
not published to NuGet. Linux/macOS target; currently validated on macOS arm64.

## Build and install

Build the [native C library](c-client.html), then:

```sh
dotnet build csharp-smkv/Smkv/Smkv.csproj
dotnet pack csharp-smkv/Smkv/Smkv.csproj -o csharp-smkv/packages
```

Reference the project from your app or install the locally built `SimpleMagic.Smkv`
package. The package does **not** include native binaries. Set `SMKV_LIBRARY` to the
absolute path to `libsmkv.so` / `libsmkv.dylib`, or install it where .NET's native
loader can find it. OpenSSL and json-c must also be installed. Build native binaries
for the same OS/architecture as the process.

## Usage

```csharp
using SimpleMagic.Smkv;
using System.Text;

using var client = new Client("127.0.0.1:7379");
byte[] key = Encoding.UTF8.GetBytes("42");
client.Put(key, [0, 1], new WriteOptions(TtlMs: 60000, Sync: true));
byte[] value = client.Get(key);
var users = client.GetTable("users");
users.Put(key, new Dictionary<string, object> { ["name"] = "Ada", ["visits"] = 1L });
Console.WriteLine(users.Get(key)["name"]);
```

Columns accept byte[], string, bool, signed integers (plus byte/ushort/uint), and
double. Reads preserve int64 as long. `Get` supports projection; `Update` atomically
sets/removes columns. `WriteOptions` exposes TTL, local sync, replica ack, and durable
replica ack. Omitted TTL means no expiry on put and preserves expiry on update;
zero expires immediately. Delete rejects TTL.

`Client.Cluster("host:7381", "other:7381")` uses **management** seeds and discovers
owners on first use. `Get(key, replica: true)` explicitly permits stale reads.
For configuration, pass `IDictionary<string, object?>` using the
[C JSON schema](c-client.html#configuration-routing-and-security).
`security` and `management_security` are independent. Their `ca` paths enable verified
TLS; `name`/`token` enable auth. Both are optional, with no automatic TLS downgrade.

## Lifecycle and errors

Use `using`/`Dispose()`. Client methods are thread-safe and serialize one request per
instance. Create a bounded application pool for concurrency. Dispose interrupts I/O
and waits for active calls before freeing the native handle.

`SmkvException.Code` distinguishes not-found (1), server statuses, and negative client
errors. `OutcomeUnknown` means a write may have completed; do not blindly retry.
Only explicit WrongOwner triggers an automatic retry. Default timeout is five
seconds including lock wait/discovery; native DNS may outlive it. Default limits
are 1 KiB keys and 1 MiB values; configure limits and timeout via the native schema.

No asynchronous API, CancellationToken support, scans, batch operations, Windows
qualification, or performance guarantee in this initial release. See
[native limits](c-client.html#lifecycle-and-limits) and [tests](sdk-clients.html#initial-release-limits).

Run `dotnet run --project csharp-smkv/Example -- 127.0.0.1:7379` after setting
`SMKV_LIBRARY`, against a disposable node. This writes expiring example records.

## Logical databases

Select the database when constructing the client (or cluster client):

```csharp
new Client(new Dictionary<string, object?> { ["endpoint"] = "127.0.0.1:7379", ["database"] = "orders" })
```

Omitting the option uses `default` and preserves existing wire keys. Named
databases require database-aware development servers (cluster protocol 5, or 6
with experimental group sync). Names use 1–64 ASCII letters, digits, `_` or `-`.
The selection scopes raw keys and all table operations, including replica reads.
The complete database-prefixed key is hashed for routing and counts against the
key-size limit. Databases share cluster capacity and durability settings.

Use the matching database-aware native library and, for Java, JNI bridge. These
bindings require the ABI 2 constructor `smkv_create_v2`; an older library fails to
load or construct a client rather than silently selecting the default database.
