PostgreSQL · Create
Ids that aren't numbers: text and uuid
Ids that aren't numbers, in three scenarios: a text id you supply (a country code), a uuid the database generates, and a uuid your code generates.
Set up for this page
Besides the sample itself, it uses SampleContext.cs (the dbContext every sample is given); SampleOutput.cs (Step and Show, which print), in the files below.
1 Text id you supply
A text id you supply: the country code. Supplied means you always set it.
Already in scope: connectionString (string)
var schema = ArxSchemaCatalog.Create()
.Table("country", ArxIdColumn.Supplied<string>("code"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var country = new ArxEntity("country");
country["code"] = "PT";
country["name"] = "Portugal";
ArxRecordId id = await service.CreateAsync(country);
// A text id is read with AsString().
Console.WriteLine($"created country {id.AsString()}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT code, name
FROM country
WHERE code = 'PT';Expect: 1 row, Portugal.
2 Uuid the database makes
A uuid the database generates (DEFAULT gen_random_uuid()): leave the id out.
Already in scope: connectionString (string)
var schema = ArxSchemaCatalog.Create()
.Table("device", ArxIdColumn.Generated<Guid>("id"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var device = new ArxEntity("device");
device["serial_number"] = "DEV-0001";
ArxRecordId id = await service.CreateAsync(device);
// A uuid is read with AsGuid().
Console.WriteLine($"created device {id.AsGuid()}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT id, serial_number
FROM device
WHERE serial_number = 'DEV-0001';Expect: 1 row, with the uuid the database generated.
3 Uuid your code makes
A uuid your code generates: set the id, and it's written as given.
Already in scope: connectionString (string)
// The same declaration as scenario 2: Generated means the database CAN fill it in, not that it must.
var schema = ArxSchemaCatalog.Create()
.Table("device", ArxIdColumn.Generated<Guid>("id"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var myId = Guid.NewGuid();
var device = new ArxEntity("device");
device["id"] = myId;
device["serial_number"] = "DEV-0002";
ArxRecordId id = await service.CreateAsync(device);
Console.WriteLine($"created device {id.AsGuid()} (the same as myId: {id.AsGuid() == myId})");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT id, serial_number
FROM device
WHERE serial_number = 'DEV-0002';Expect: 1 row, with the uuid the sample printed (myId).
Run the complete sample
The code above comes from one program, built in a fresh project and run against the database. To run it yourself, here is every file and step.
The program, its files and how to run it
Run it locally
- .NET SDK: .NET SDK 10.0.100 or later 10.0.x (target
net10.0). - Create the project:
Terminal dotnet new console -n ArxSample -f net10.0 cd ArxSample - Install the packages:
Terminal dotnet add package ARX.SDK.PostgreSql --version 1.0.0-rc.1 - Database: a PostgreSQL 16 (tested with 16.15) database with the sample schema.
- Configuration: set
ARX_SAMPLES_POSTGRESQLto its connection string. Nothing is hard-coded. - Source code: replace
Program.csand add the 3 other files below, with the file names shown. - Run it:
Terminal dotnet run - Expected output: below.
The files
Runs the sample. Generated for this page; it reads the connection string from the environment.
using ArxSamples.PostgreSql;
using ArxSamples.PostgreSql.Operations.Create.Basics;
// The connection string comes from the environment, never from the code (see "Configure the connection").
var connectionString = Environment.GetEnvironmentVariable("ARX_SAMPLES_POSTGRESQL")
?? throw new InvalidOperationException("Set the ARX_SAMPLES_POSTGRESQL environment variable to your PostgreSQL connection string.");
await new Basic4_TextAndUuidIds().RunAsync(new SampleContext(connectionString));
The sample, as it is in the repository.
using ARX.SDK.PostgreSql.Services;
using ARX.SDK.Services;
using static ArxSamples.PostgreSql.SampleOutput;
namespace ArxSamples.PostgreSql.Operations.Create.Basics;
/// <summary>
/// Ids that aren't numbers, in three scenarios: a text id you supply (a country code), a uuid the database generates,
/// and a uuid your code generates.
/// </summary>
public sealed class Basic4_TextAndUuidIds : ISample
{
public string Name => "create-basics-4-text-and-uuid-ids";
public string Title => "Ids that aren't numbers: text and uuid";
public async Task RunAsync(SampleContext dbContext)
{
await Scenario1_ATextIdYouSupplyAsync(dbContext.ConnectionString);
await Scenario2_AUuidTheDatabaseGeneratesAsync(dbContext.ConnectionString);
await Scenario3_AUuidYourCodeGeneratesAsync(dbContext.ConnectionString);
}
/// <summary>1. A text id you supply: the country code. Supplied means you always set it.</summary>
private static async Task Scenario1_ATextIdYouSupplyAsync(string connectionString)
{
Step("1. Text id you supply");
var schema = ArxSchemaCatalog.Create()
.Table("country", ArxIdColumn.Supplied<string>("code"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var country = new ArxEntity("country");
country["code"] = "PT";
country["name"] = "Portugal";
ArxRecordId id = await service.CreateAsync(country);
// A text id is read with AsString().
Show($"created country {id.AsString()}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT code, name
* FROM country
* WHERE code = 'PT';
* -- Expect: 1 row, Portugal.
* ===========================================================
*/
}
/// <summary>2. A uuid the database generates (DEFAULT gen_random_uuid()): leave the id out.</summary>
private static async Task Scenario2_AUuidTheDatabaseGeneratesAsync(string connectionString)
{
Step("2. Uuid the database makes");
var schema = ArxSchemaCatalog.Create()
.Table("device", ArxIdColumn.Generated<Guid>("id"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var device = new ArxEntity("device");
device["serial_number"] = "DEV-0001";
ArxRecordId id = await service.CreateAsync(device);
// A uuid is read with AsGuid().
Show($"created device {id.AsGuid()}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT id, serial_number
* FROM device
* WHERE serial_number = 'DEV-0001';
* -- Expect: 1 row, with the uuid the database generated.
* ===========================================================
*/
}
/// <summary>3. A uuid your code generates: set the id, and it's written as given.</summary>
private static async Task Scenario3_AUuidYourCodeGeneratesAsync(string connectionString)
{
Step("3. Uuid your code makes");
// The same declaration as scenario 2: Generated means the database CAN fill it in, not that it must.
var schema = ArxSchemaCatalog.Create()
.Table("device", ArxIdColumn.Generated<Guid>("id"))
.Build();
var service = new ArxPgDbService(connectionString, schema);
var myId = Guid.NewGuid();
var device = new ArxEntity("device");
device["id"] = myId;
device["serial_number"] = "DEV-0002";
ArxRecordId id = await service.CreateAsync(device);
Show($"created device {id.AsGuid()} (the same as myId: {id.AsGuid() == myId})");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT id, serial_number
* FROM device
* WHERE serial_number = 'DEV-0002';
* -- Expect: 1 row, with the uuid the sample printed (myId).
* ===========================================================
*/
}
}
What every sample is given: the connection string (and the ISample interface the samples implement).
namespace ArxSamples.PostgreSql;
/// <summary>One documentation sample: a scenario a real application has, shown end to end.</summary>
public interface ISample
{
/// <summary>The name to run it alone: <c>dotnet run -- <name></c>.</summary>
string Name { get; }
/// <summary>One line on what it shows.</summary>
string Title { get; }
Task RunAsync(SampleContext dbContext);
}
/// <summary>
/// What a sample is given. Every sample gets the connection string; the application's service and catalog
/// (SampleContext.Application.cs) and the plain Npgsql read-back helper (SampleContext.Direct.cs) live in their own
/// files, so a sample needs only the files it uses.
/// </summary>
public sealed partial class SampleContext
{
public SampleContext(string connectionString)
{
ConnectionString = connectionString;
}
public string ConnectionString { get; }
}
How the samples print: Step for each scenario, Show for what it did, ShowError for an error caught on purpose.
using ARX.SDK;
namespace ArxSamples.PostgreSql;
/// <summary>How the samples print: a numbered step for each scenario, then what it did.</summary>
public static class SampleOutput
{
/// <summary>The start of a scenario: <c>Step("1. By the id Create returned")</c>.</summary>
public static void Step(string text) => Console.WriteLine($" > {text}");
/// <summary>What the scenario did.</summary>
public static void Show(string text) => Console.WriteLine($" {text}");
/// <summary>An ARX error the scenario caught on purpose.</summary>
public static void ShowError(ArxException exception)
=> Console.WriteLine($" caught {exception.GetType().Name}: {exception.Message}");
}
Expected output
What dotnet run printed when the sample was verified, on a freshly created sample schema. Ids differ when the tables already hold rows.
> 1. Text id you supply
created country PT
> 2. Uuid the database makes
created device c46b1e09-d75d-4360-bfe0-57e705c22bf9
> 3. Uuid your code makes
created device c1382b33-3f39-4272-b4c2-cf2ac796beaf (the same as myId: True)