SQL Server

Retrieve

6 samples, from the least code that works to complete workflows.

What a read does

Retrieve One record by id (RetrieveAsync("account", id, columns)), or by a key or columns (RetrieveAsync(entity, new ArxRetrieveOptions { Match = ArxMatch.Key("email") })). Null when nothing matches; ARX2003 when a key or columns match more than one row
What it reads from A table, a view (in any schema: reporting.vw_product_catalogue), or a table-valued function (ArxRowSource.Function("fn", value), arguments by position). Procedures and scalar functions are Execute's. The samples name views vw_, functions fn_ and procedures sp_
Columns The ones asked for, plus the declared id (so RecordId is set); none means all. column._lk.table.c1,c2 joins the referenced table directly (columns column.c1); a link entity's columns come back as alias.column
Values read back date → DateOnly, time → TimeOnly, datetime2 → DateTime (Kind Unspecified), datetimeoffset → DateTimeOffset with its offset; NULL is a null attribute, "" stays ""
Lookups A column declared with .Lookup(...) reads back as an ArxEntityReference, its Name filled from the referenced table's .DisplayName(...)
Isolation Reads on connections ARX opens are READ COMMITTED, whatever another user of the pooled connection left set. Under it a row another transaction changed but hasn't committed makes the read wait (until the commit or the command timeout); a database with READ_COMMITTED_SNAPSHOT on reads the last committed version instead
Security A name carrying SQL (a sort field, a filter field, a table from a request) is ARX1017, refused before the database; a name that breaks the name rules (a space, a hyphen) is ARX1003, and a well-formed name the table doesn't have (a misspelling) comes back from the database as ARX5002
Without a catalog By id or key, the table is read from the database first to find the row (one more round trip per call, so much slower than with a catalog: meant for simple CRUD and small applications). The values come back as they would with a catalog, so without one a read sets no RecordId (ask for the id column) and a lookup column is its plain value (Basic4)

Reference

Value types read back

SQL Server column Reads back as Notes
nvarchar(n), varchar(n), nchar(n), nvarchar(max) string nchar(n) keeps its padding spaces; "" stays ""
tinyint / smallint / int / bigint byte / short / int / long
decimal(p, s), money decimal More than 28 significant digits: ARX4001 ValueOutOfRange
real / float float / double
bit bool
uniqueidentifier Guid
datetimeoffset DateTimeOffset The clock time and the offset it was stored with
datetime2, datetime, smalldatetime DateTime, Kind Unspecified The clock time as stored: SQL Server keeps no zone
date / time DateOnly / TimeOnly
varbinary(n), varbinary(max), rowversion byte[]
JSON in nvarchar(max) string SQL Server 2022 has no JSON type: the text as stored
sql_variant the value's own type
An alias type (CREATE TYPE … FROM nvarchar(320)) Its base type
A declared lookup (.Lookup(...)) ArxEntityReference Name from the referenced table's .DisplayName(...)
A selection set column Its stored code entity.GetSelectionSet(column, set, catalog) gives the option
NULL null The attribute is present, with a null value

RealCase1_EveryDataTypeReadBack writes one row of every type with Create and prints each value's .NET type as it reads back.

Aggregates

Aggregate On SQL Server Reads back as
Count, CountBig, CountDistinct, CountBigDistinct COUNT_BIG(*), or of the attribute when one is named long
Avg AVG(column * 1.0): SQL Server's own AVG of integers is an integer (2 and 3 give 2) decimal
Sum, Min, Max as they are (a Sum of int past 2³¹ is an overflow error, ARX4001, not a wrong value) the column's type

Error codes a read can raise

Code When
ARX1001 InvalidArgument An id of the wrong type or one that can't exist; a NoIdColumn table read by id; an operator without the values it needs (Between with one value, Equal with NULL, NULL in an In list); paging values below 1; Top with PageInfo; an alias used twice or reserved; a link asking for all columns
ARX1002, ARX1003, ARX1004 A missing table name; an invalid name; a column asked for twice
ARX1008 InvalidConnection A connection with an open transaction, given without that transaction
ARX1016 IdNotDeclared Retrieve by id or key on an undeclared table; a _lk join on an undeclared table without ~column
ARX1017 SuspectedInjection A table, column, alias, condition, order, group-by, aggregate, function or argument name carrying SQL
ARX2003 MultipleRecordsMatched Retrieve by a key or columns found more than one row
ARX4001 ValueOutOfRange A decimal larger than a .NET decimal can hold; an aggregate that overflows
ARX4003 InvalidValueFormat Text compared with a number column that doesn't convert ('forty' against an int)
ARX4004 DataTypeMismatch A value of a type the column can't be compared with; a function given more arguments than it has
ARX5001, ARX5002 A table, view or function that doesn't exist (a scalar function read as a table, too); a column that doesn't exist, or a selected column that isn't grouped
ARX6001 PermissionDenied No SELECT permission
ARX7003 Timeout CommandTimeout exceeded (a read waiting for another transaction's lock, too)
ARX8001 NotSupported A removed column form (._opt, ignoredefault.); paging a source with no order and no declared id; a function with named arguments or declared result columns; full-text search on a column without a full-text index; a procedure

The samples

Basics

The least code that works.

1Retrieve one recordStandalone

The smallest read: one record, in three scenarios. The usual way first (the id CreateAsync returned, and the columns you want), then a text id, then an id nobody has: Retrieve returns null, not an error.

2Choose the columns to readStandalone

Which columns come back, in three scenarios: the ones you ask for (plus the id); all of them; and how an empty value differs from a NULL one.

3Find a record by id, key or columnsStandalone

The three ways to find one record, in four scenarios: by id, by a declared key, by any columns, and what happens when columns match more than one row.

4Retrieve without a catalogStandalone

One record read on a service created with only a connection string, in two scenarios: by the id, which ARX finds from the table's primary key; and by a key, the unique account number.

Real cases

What an application does: a small CRM and product catalogue.

1Every data type, written and read backProgressive

What each SQL Server type reads back as, in one scenario: a row of data_type_showcase is written with Create and read with Retrieve, and each attribute's .NET type is printed.

Advanced cases

Dependency injection, transactions, batch scopes and setting the service up.

1Read your own writes in an ARX transactionAdvanced

Reads inside an ARX transaction, in two scenarios: a read sees the transaction's own uncommitted writes, another connection doesn't; and a check that reads before it commits, rolling back when the check fails.