PostgreSQL · Update
An edit form changes some account details
An "edit account" form, in three scenarios: the fields the user changed are written and the rest kept; a field the user emptied is cleared; the form sends the id it was opened with.
Set up for this page
The scenarios build on the sample application: SampleContext.cs (the dbContext every sample is given); SampleOutput.cs (Step and Show, which print); SampleContext.Application.cs (dbContext.Service, the application's ARX service); SampleCatalog.cs (the tables' ids, keys, lookups and display names).
1 Write only the fields the user changed
The form posts only what the user changed. Each posted field becomes an attribute; nothing else is touched.
Already in scope: service (ArxPgDbService), id (ArxRecordId)
var posted = new Dictionary<string, object>
{
["employee_count"] = 75,
["annual_revenue"] = 4_800_000.00m
};
var change = new ArxEntity("account");
change.RecordId = id;
foreach (var (field, value) in posted)
{
change[field] = value;
}
var changed = await service.UpdateAsync(change);
Console.WriteLine($"{changed} row changed: {string.Join(", ", posted.Keys)}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT name, website, employee_count, annual_revenue
FROM account
WHERE account_number = 'ACC-U601';Expect: 1 row, Alpine Ski House, https://alpineskihouse.example, employee_count 75, annual_revenue 4800000.00.
2 An emptied field is cleared
The user emptied the website box: the form sends null, and the column is cleared.
Already in scope: service (ArxPgDbService), id (ArxRecordId)
var change = new ArxEntity("account");
change.RecordId = id;
change["website"] = null;
await service.UpdateAsync(change);
Console.WriteLine("website cleared");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT website
FROM account
WHERE account_number = 'ACC-U602';Expect: 1 row, NULL.
3 The id comes back with the form
The form was opened with the account's id in a hidden field: it comes back as the id attribute.
Already in scope: service (ArxPgDbService), id (ArxRecordId)
var hiddenField = id.AsInt64().ToString();
var change = new ArxEntity("account");
change["id"] = long.Parse(hiddenField);
change["name"] = "Alpine Ski House Ltd.";
await service.UpdateAsync(change);
Console.WriteLine($"account {hiddenField} renamed");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT name
FROM account
WHERE account_number = 'ACC-U603';Expect: 1 row, Alpine Ski House Ltd.
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: add the files of the sample application this sample uses (
SampleContext.cs,SampleOutput.cs,SampleContext.Application.cs,SampleCatalog.cs), then replaceProgram.csand add the other file 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.Update.RealCases;
// 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 RealCase1_ChangeAccountDetails().RunAsync(new SampleContext(connectionString));
The sample, as it is in the repository.
using ARX.SDK.Services;
using static ArxSamples.PostgreSql.SampleOutput;
namespace ArxSamples.PostgreSql.Operations.Update.RealCases;
/// <summary>
/// An "edit account" form, in three scenarios: the fields the user changed are written and the rest kept; a field the
/// user emptied is cleared; the form sends the id it was opened with.
/// </summary>
public sealed class RealCase1_ChangeAccountDetails : ISample
{
public string Name => "update-real-1-change-account-details";
public string Title => "An edit form changes some account details";
public async Task RunAsync(SampleContext dbContext)
{
// One account per scenario, so each scenario's check holds after the whole sample has run.
await Scenario1_OnlyTheChangedFieldsAsync(dbContext, await CreateAccountAsync(dbContext, "ACC-U601"));
await Scenario2_AnEmptiedFieldIsClearedAsync(dbContext, await CreateAccountAsync(dbContext, "ACC-U602"));
await Scenario3_TheFormSendsTheIdAsync(dbContext, await CreateAccountAsync(dbContext, "ACC-U603"));
}
private static async Task<ArxRecordId> CreateAccountAsync(SampleContext dbContext, string number)
{
var account = new ArxEntity("account");
account["name"] = "Alpine Ski House";
account["account_number"] = number;
account["website"] = "https://alpineskihouse.example";
account["employee_count"] = 60;
account["annual_revenue"] = 4_200_000.00m;
return await dbContext.Service.CreateAsync(account);
}
/// <summary>1. The form posts only what the user changed. Each posted field becomes an attribute; nothing else is touched.</summary>
private static async Task Scenario1_OnlyTheChangedFieldsAsync(SampleContext dbContext, ArxRecordId id)
{
Step("1. Write only the fields the user changed");
var posted = new Dictionary<string, object>
{
["employee_count"] = 75,
["annual_revenue"] = 4_800_000.00m
};
var change = new ArxEntity("account");
change.RecordId = id;
foreach (var (field, value) in posted)
{
change[field] = value;
}
var changed = await dbContext.Service.UpdateAsync(change);
Show($"{changed} row changed: {string.Join(", ", posted.Keys)}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT name, website, employee_count, annual_revenue
* FROM account
* WHERE account_number = 'ACC-U601';
* -- Expect: 1 row, Alpine Ski House, https://alpineskihouse.example, employee_count 75, annual_revenue 4800000.00.
* ===========================================================
*/
}
/// <summary>2. The user emptied the website box: the form sends null, and the column is cleared.</summary>
private static async Task Scenario2_AnEmptiedFieldIsClearedAsync(SampleContext dbContext, ArxRecordId id)
{
Step("2. An emptied field is cleared");
var change = new ArxEntity("account");
change.RecordId = id;
change["website"] = null;
await dbContext.Service.UpdateAsync(change);
Show("website cleared");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT website
* FROM account
* WHERE account_number = 'ACC-U602';
* -- Expect: 1 row, NULL.
* ===========================================================
*/
}
/// <summary>3. The form was opened with the account's id in a hidden field: it comes back as the id attribute.</summary>
private static async Task Scenario3_TheFormSendsTheIdAsync(SampleContext dbContext, ArxRecordId id)
{
Step("3. The id comes back with the form");
var hiddenField = id.AsInt64().ToString();
var change = new ArxEntity("account");
change["id"] = long.Parse(hiddenField);
change["name"] = "Alpine Ski House Ltd.";
await dbContext.Service.UpdateAsync(change);
Show($"account {hiddenField} renamed");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT name
* FROM account
* WHERE account_number = 'ACC-U603';
* -- Expect: 1 row, Alpine Ski House Ltd.
* ===========================================================
*/
}
}
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. Write only the fields the user changed
1 row changed: employee_count, annual_revenue
> 2. An emptied field is cleared
website cleared
> 3. The id comes back with the form
account 3 renamed