MySQL · Create
A sign-up form creates an account
A sign-up form creates a customer account, in three scenarios: the account from the form (columns left out get their database defaults), a subsidiary that points at its parent, and form fields the table doesn't have (ArxIgnore).
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); SampleContext.Direct.cs (dbContext.Direct); MySqlDirectHelper.cs (the checks behind dbContext.Direct).
dbContext.Direct is the samples' own checking code on the plain driver, not part of ARX: leave it out of your application.
1 Create the account from the form
The account from the sign-up form. guid, status and created_on aren't set: the database fills them in.
Already in scope: service (ArxMySqlDbService)
var account = new ArxEntity("account");
account["name"] = "Northwind Traders";
account["account_number"] = "ACC-10001";
account["industry"] = new ArxSelectionSetValue("Industry", Industry.Retail);
account["website"] = "https://northwind.example";
account["annual_revenue"] = 12_500_000.00m;
account["employee_count"] = 240;
account["is_key_account"] = true;
account["founded_on"] = new DateOnly(1998, 4, 1);
account["modified_on"] = DateTime.UtcNow;
var id = await service.CreateAsync(account);
Console.WriteLine($"account {id} (also on account.RecordId)");
return account;Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT id, name, account_number, industry, website, annual_revenue, guid, status, created_on
FROM account
WHERE account_number = 'ACC-10001';Expect: 1 row; guid, status and created_on are the database defaults.
2 Add a subsidiary that points at its parent
A subsidiary account points at its parent with a lookup.
Already in scope: service (ArxMySqlDbService), parent (ArxEntity)
var subsidiary = new ArxEntity("account");
subsidiary["name"] = "Northwind Traders (Canada)";
subsidiary["account_number"] = "ACC-10002";
subsidiary["parent_account_id"] = new ArxEntityReference("account", parent.RecordId);
var id = await service.CreateAsync(subsidiary);Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT s.name, s.account_number, s.parent_account_id, p.name AS parent
FROM account s
JOIN account p ON p.id = s.parent_account_id
WHERE s.account_number = 'ACC-10002';Expect: 1 row, Northwind Traders (Canada), parent Northwind Traders.
3 Form fields the table doesn't have are marked ArxIgnore
A form field the table doesn't have stays on the entity, marked ArxIgnore, and isn't written.
Already in scope: service (ArxMySqlDbService)
var fromForm = new ArxEntity("account");
fromForm["name"] = "Contoso Pharmaceuticals";
fromForm["industry"] = new ArxSelectionSetValue("Industry", Industry.Healthcare);
fromForm["display_label"] = new ArxIgnore();
// The id column "id" is declared Generated, and the form doesn't set it, so the database fills it in. An id you do
// set is written as given, so leave the id attribute out unless you mean it.
var id = await service.CreateAsync(fromForm);
Console.WriteLine($"account {id}: display_label wasn't sent, and the database chose the id");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT id, name, industry
FROM account
WHERE name = 'Contoso Pharmaceuticals' AND account_number IS NULL;Expect: 1 row, industry 3 (Healthcare); there is no display_label column.
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.MySQL --version 1.0.0-rc.1 - Database: a MySQL 8.4 (tested with 8.4.13) database with the sample schema.
- Configuration: set
ARX_SAMPLES_MYSQLto 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,SampleContext.Direct.cs,MySqlDirectHelper.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.MySQL;
using ArxSamples.MySQL.Operations.Create.RealCases;
// The connection string comes from the environment, never from the code (see "Configure the connection").
var connectionString = Environment.GetEnvironmentVariable("ARX_SAMPLES_MYSQL")
?? throw new InvalidOperationException("Set the ARX_SAMPLES_MYSQL environment variable to your MySQL connection string.");
await new RealCase1_SignUpAnAccount().RunAsync(new SampleContext(connectionString));
The sample, as it is in the repository.
using ARX.SDK.Models;
using ARX.SDK.Services;
using static ArxSamples.MySQL.SampleOutput;
namespace ArxSamples.MySQL.Operations.Create.RealCases;
/// <summary>
/// A sign-up form creates a customer account, in three scenarios: the account from the form (columns left out get their
/// database defaults), a subsidiary that points at its parent, and form fields the table doesn't have (ArxIgnore).
/// </summary>
public sealed class RealCase1_SignUpAnAccount : ISample
{
public string Name => "create-real-1-sign-up-an-account";
public string Title => "A sign-up form creates an account";
public async Task RunAsync(SampleContext dbContext)
{
var account = await Scenario1_CreateTheAccountFromTheFormAsync(dbContext);
await Scenario2_ASubsidiaryPointsAtItsParentAsync(dbContext, account);
await Scenario3_FormFieldsTheTableDoesNotHaveAsync(dbContext);
}
/// <summary>1. The account from the sign-up form. guid, status and created_on aren't set: the database fills them in.</summary>
private static async Task<ArxEntity> Scenario1_CreateTheAccountFromTheFormAsync(SampleContext dbContext)
{
Step("1. Create the account from the form");
var account = new ArxEntity("account");
account["name"] = "Northwind Traders";
account["account_number"] = "ACC-10001";
account["industry"] = new ArxSelectionSetValue("Industry", Industry.Retail);
account["website"] = "https://northwind.example";
account["annual_revenue"] = 12_500_000.00m;
account["employee_count"] = 240;
account["is_key_account"] = true;
account["founded_on"] = new DateOnly(1998, 4, 1);
account["modified_on"] = DateTime.UtcNow;
var id = await dbContext.Service.CreateAsync(account);
Show($"account {id} (also on account.RecordId)");
// guid, status and created_on weren't set: MySQL filled in their defaults.
var stored = await dbContext.Direct.RowAsync("account", id.AsInt64());
Show($"defaults: guid {stored["guid"]}, status {stored["status"]}, created_on {stored["created_on"]:u}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT id, name, account_number, industry, website, annual_revenue, guid, status, created_on
* FROM account
* WHERE account_number = 'ACC-10001';
* -- Expect: 1 row; guid, status and created_on are the database defaults.
* ===========================================================
*/
return account;
}
/// <summary>2. A subsidiary account points at its parent with a lookup.</summary>
private static async Task Scenario2_ASubsidiaryPointsAtItsParentAsync(SampleContext dbContext, ArxEntity parent)
{
Step("2. Add a subsidiary that points at its parent");
var subsidiary = new ArxEntity("account");
subsidiary["name"] = "Northwind Traders (Canada)";
subsidiary["account_number"] = "ACC-10002";
subsidiary["parent_account_id"] = new ArxEntityReference("account", parent.RecordId);
var id = await dbContext.Service.CreateAsync(subsidiary);
Show($"subsidiary {id}, parent_account_id {(await dbContext.Direct.RowAsync("account", id.AsInt64()))["parent_account_id"]}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT s.name, s.account_number, s.parent_account_id, p.name AS parent
* FROM account s
* JOIN account p ON p.id = s.parent_account_id
* WHERE s.account_number = 'ACC-10002';
* -- Expect: 1 row, Northwind Traders (Canada), parent Northwind Traders.
* ===========================================================
*/
}
/// <summary>3. A form field the table doesn't have stays on the entity, marked ArxIgnore, and isn't written.</summary>
private static async Task Scenario3_FormFieldsTheTableDoesNotHaveAsync(SampleContext dbContext)
{
Step("3. Form fields the table doesn't have are marked ArxIgnore");
var fromForm = new ArxEntity("account");
fromForm["name"] = "Contoso Pharmaceuticals";
fromForm["industry"] = new ArxSelectionSetValue("Industry", Industry.Healthcare);
fromForm["display_label"] = new ArxIgnore();
// The id column "id" is declared Generated, and the form doesn't set it, so the database fills it in. An id you do
// set is written as given, so leave the id attribute out unless you mean it.
var id = await dbContext.Service.CreateAsync(fromForm);
Show($"account {id}: display_label wasn't sent, and the database chose the id");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT id, name, industry
* FROM account
* WHERE name = 'Contoso Pharmaceuticals' AND account_number IS NULL;
* -- Expect: 1 row, industry 3 (Healthcare); there is no display_label column.
* ===========================================================
*/
}
}
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. Create the account from the form
account 1 (also on account.RecordId)
defaults: guid daea56e4-de48-11f1-8688-429545a106a5, status ACTIVE, created_on 2026-11-12 03:26:31Z
> 2. Add a subsidiary that points at its parent
subsidiary 2, parent_account_id 1
> 3. Form fields the table doesn't have are marked ArxIgnore
account 3: display_label wasn't sent, and the database chose the id