---
name: arx-sdk
description: Write, review and fix C# code that uses ARX.SDK by MigsLab, the entity-based data access library for .NET, with its providers for PostgreSQL (ARX.SDK.PostgreSql), SQL Server (ARX.SDK.SQL), MySQL (ARX.SDK.MySQL), MongoDB (ARX.SDK.MongoDb) and DynamoDB (ARX.SDK.DynamoDb). Use when a project references an ARX.SDK package, or code uses ArxEntity, ArxQueryExpression, ArxSchemaCatalog, an Arx...DbService or an ARX error code (ARX1003, ARX8001 and the like).
license: Apache-2.0
compatibility: ARX.SDK 1.0.0-rc.1 on .NET 10. Reading the references needs no tools; verifying code needs the .NET SDK.
metadata:
  arx-sdk-version: "1.0.0-rc.1"
  source: "https://arx.migslab.com"
---

# ARX.SDK

ARX.SDK is a data access library for .NET: one dictionary-driven entity model (`ArxEntity`, `ArxQueryExpression`,
`ArxSchemaCatalog`) runs against several databases through one provider package per database. It is not an ORM: there
are no entity classes, no change tracking, no LINQ; a row is an `ArxEntity` whose values are read and written by column
name. This skill targets ARX.SDK **1.0.0-rc.1**: if the project references another version, say so before relying on it.

Everything in `references/` is generated from the library's doc comments, its operation guides and samples that were
compiled and run against each database. Prefer it to memory: ARX's API is not in most training data, and names that
look plausible are often wrong.

## 1. Find the provider

Read the project's `.csproj` (or `Directory.Packages.props`) for the ARX.SDK package it references, then use that
provider's folder. A project may reference more than one.

| Package | Database | Service | Connection | References |
|---|---|---|---|---|
| `ARX.SDK.PostgreSql` | PostgreSQL | `ArxPgDbService` | `ArxPgConnection` | `references/postgresql/` (files `arx-postgresql-*.md`) |
| `ARX.SDK.SQL` | SQL Server | `ArxMsSqlDbService` | `ArxMsSqlConnection` | `references/sql/` (files `arx-sql-*.md`) |
| `ARX.SDK.MySQL` | MySQL | `ArxMySqlDbService` | `ArxMySqlConnection` | `references/mysql/` (files `arx-mysql-*.md`) |
| `ARX.SDK.MongoDb` | MongoDB | `ArxMongoDbService` | `ArxMongoConnection` | `references/mongodb/` (files `arx-mongodb-*.md`) |
| `ARX.SDK.DynamoDb` | Amazon DynamoDB | `ArxDynamoDbService` | `ArxDynamoConnection` | `references/dynamodb/` (files `arx-dynamodb-*.md`) |

If no ARX.SDK package is referenced, ask which database the code is for before writing any.

## 2. Read before writing

In the provider's folder, read these first, every time:

1. `arx-<provider>-guide.md`: the rules for that provider, its packages and setup, and a quick reference of each
   operation. Its "Instructions for the assistant" are binding.
2. `arx-<provider>-types.md`: every public type, constructor, property and method, with their parameters. **Use only
   what is listed there.** If a type or member isn't listed, ARX doesn't have it: say so instead of inventing a name.

Then the file for the task:

| Task | File in the provider's folder |
|---|---|
| Insert one row: ids, keys, lookups, values | `arx-<provider>-create.md` |
| Insert many rows in one call, imports | `arx-<provider>-create-multiple.md` |
| Change one row, found by id, key or columns | `arx-<provider>-update.md` |
| Change many rows in one call, all or nothing | `arx-<provider>-update-multiple.md` |
| Remove one row | `arx-<provider>-delete.md` |
| Remove many rows, by ids or entities | `arx-<provider>-delete-multiple.md` |
| Read one row by id, key or columns | `arx-<provider>-retrieve.md` |
| Query many rows: criteria, columns, order, paging, links, aggregates | `arx-<provider>-retrieve-multiple.md` |
| Stored procedures and functions (SQL providers only) | `arx-<provider>-execute.md` |
| Which .NET type goes in which column, dates and times | `arx-<provider>-data-types.md` |
| What an `ArxException` code means, whether to retry | `arx-<provider>-error-codes.md` |
| How fast ARX is next to the alternatives | `arx-<provider>-benchmarks.md` |

The operation files hold every sample of the operation: each scenario's code and the database query that checks what
it did. Start from the closest sample and adapt it; name the sample when it helps the developer find more.

Topics that span providers are in `references/guides/`:

| Topic | File |
|---|---|
| Catching errors, retries, what a first connection's errors mean | `references/guides/errors-in-practice.md` |
| Moving code from one provider to another | `references/guides/switching-providers.md` |
| Coming from EF Core or Dapper | `references/guides/coming-from-ef-core-or-dapper.md` |
| Service lifetime, connections, transactions, cancellation, retries, security | `references/guides/running-in-production.md` |
| Existing tables: names, ids, keys, aliases for odd column names | `references/guides/using-your-own-tables.md` |
| Logging every call, tracing, metrics | `references/guides/logging-and-tracing.md` |

## 3. The model, in short

- **A row is an `ArxEntity`**: `new ArxEntity("account")`, then `account["name"] = "Northwind Traders";`. Table and
  column names are the database's, as strings.
- **Tables are declared once, at startup**, in an `ArxSchemaCatalog` given to the service: each table's id column
  (`ArxIdColumn.Generated<long>("id")`, `ArxIdColumn.Supplied<string>("code")` or `ArxIdColumn.NoIdColumn`), its
  business keys, lookups and aliases. ARX never guesses an id: an undeclared table is ARX1016. Only a SQL service
  created **without** a catalog (PostgreSQL, SQL Server, MySQL) reads each table's primary key and column types from
  the database before the call: much slower, for simple CRUD in small applications; a table without a usable primary
  key is then ARX1019. Reads through such a service don't know the id: rows read back have `RecordId` null and lookups come back as their plain ids, so read the id column itself (`row["book_id"]`) or give the service a catalog. Prefer a catalog, and suggest one when an application grows.
- **One service per database**, created once and shared: the provider's service class, or `IArxDataService` where
  application code should not depend on the provider.
- **Every call is asynchronous** and takes the caller's `CancellationToken` where the method has one.
- **Create returns the id** (`ArxRecordId`, also on `entity.RecordId`); a lookup points at another record with
  `new ArxEntityReference("account", id)`.
- **Update and Delete** find rows by the id, a declared key or columns the call names (`ArxMatch`).
- **Writes by a filter**: `UpdateMultipleAsync(values, filter)` and `DeleteMultipleAsync(table, filter)` change or delete
  every row an `ArxFilterExpression` matches and return the count; the values carry no id, an empty filter needs
  `AllRows`. `ArxCreateMultipleOptions { ReturnIds = false }` creates without reading ids back. DynamoDB needs the
  filter to give a partition key (at most 100 items).
- **Reads**: `RetrieveAsync` returns null when nothing matches; `RetrieveMultipleAsync` takes an `ArxQueryExpression`.
- **Transactions** use the provider's connection type and `ArxTransaction`; batch scopes (`RunBatchAsync`) group many
  calls and commit when the body returns, never on dispose.
- **Errors** are `ArxException`s with a stable `ArxErrorCode`; retry only when `IsTransient` is true.
- **What a provider can't do is refused with `ArxNotSupportedException` (ARX8001)**, never done in part. Check
  `service.Capabilities`, or the provider guide, before using a feature that differs between databases.

## 4. Rules

1. Use ARX's types for database work. Don't write driver code (Npgsql, SqlClient, MySqlConnector, the MongoDB driver,
   the AWS SDK's requests) or SQL text for work ARX does; the provider guide says what the application still owns.
2. Never invent API. Every type and member you write must appear in the provider's types file.
3. Values are always passed as .NET values, never written into SQL or query text. Names that carry SQL or query syntax
   are refused (ARX1017); a name outside the identifier rule is ARX1003 unless declared as an alias.
4. Declare ids, keys and lookups in the schema catalog, not on each entity, once a catalog exists (both is ARX1001).
5. Dates follow the provider's data types file: never `default(DateTime)` (ARX1013), never a date as a string (PostgreSQL refuses it, ARX4004; SQL Server and MySQL convert what they can read, ARX4003 otherwise; pass `DateOnly` or `DateTime`).
6. Handle errors by `Code` or `IsTransient`, not by message text.
7. Follow the provider guide where it differs from these rules: it is the authority for its database.

## 5. Verify

Before you call the work done:

1. Check every ARX type, constructor, property and method you used against the provider's types file.
2. Build: `dotnet build`. Fix every error; don't silence one by guessing another overload.
3. If the project has tests, run them. If the change touches a table, show the developer the query that checks it,
   as the samples do, or run it when you have the database.
4. Say what you could not verify (no database, no build tools) instead of claiming it works.

## 6. Keeping this skill current

This skill is generated for one ARX.SDK version (1.0.0-rc.1). When the project moves to a newer ARX.SDK version, download
the skill again from https://arx.migslab.com (any provider's "Work with AI" pages) and replace this folder; don't edit
the references by hand, they are regenerated from the library.
