Amazon DynamoDB · Create
Catch the errors a create meets
The errors a create meets most, in three scenarios: a key that exists, a key attribute left out, and an id declared as generated, which DynamoDB can't do.
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); SampleModel.cs (the DynamoDB layout and the schema catalog); SampleContext.Direct.cs (dbContext.Direct); DynamoDirectHelper.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 A key that exists
The same customer twice: ARX3001; the first stays as it was.
Already in scope: service (ArxDynamoDbService)
var customer = new ArxEntity("customer");
customer["customer_id"] = "C-D401";
customer["name"] = "Fabrikam";
await service.CreateAsync(customer);
customer["name"] = "Fabrikam (copy)";
try
{
await service.CreateAsync(customer);
}
catch (ArxDatabaseException exception) when (exception.Code == ArxErrorCode.UniqueViolation)
{
Console.WriteLine(exception.Message);
}Check it in the database
A PartiQL statement: run it in NoSQL Workbench, or with aws dynamodb execute-statement --statement, after the code has run.
SELECT "name" FROM "crm" WHERE "PK" = 'CUSTOMER#C-D401' AND "SK" = 'PROFILE'Expect: 1 item, name "Fabrikam".
2 A key attribute left out
An order without its customer_id: its key can't be made, so nothing is sent.
Already in scope: service (ArxDynamoDbService)
var order = new ArxEntity("sales_order");
order["order_number"] = "SO-D402";
try
{
await service.CreateAsync(order);
}
catch (ArxValidationException exception)
{
Console.WriteLine(exception.Message);
}Check it in the database
A PartiQL statement: run it in NoSQL Workbench, or with aws dynamodb execute-statement --statement, after the code has run.
SELECT "SK" FROM "crm" WHERE "SK" = 'ORDER#SO-D402'Expect: no items.
3 A generated id
An id declared as generated: DynamoDB generates nothing, so ARX8001 with the advice to supply one.
Already in scope: client (IAmazonDynamoDB)
var catalog = ArxSchemaCatalog.Create().Table("product", ArxIdColumn.Generated<string>("sku")).Build();
var service = new ArxDynamoDbService(client, ArxDynamoModel.Create().Table("product", partitionKey: "sku").Build(), catalog);
var product = new ArxEntity("product");
product["sku"] = "SKU-D403";
try
{
await service.CreateAsync(product);
}
catch (ArxNotSupportedException exception)
{
Console.WriteLine(exception.Message);
}Check it in the database
A PartiQL statement: run it in NoSQL Workbench, or with aws dynamodb execute-statement --statement, after the code has run.
SELECT "sku" FROM "product" WHERE "sku" = 'SKU-D403'Expect: no items.
See also
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.DynamoDb --version 1.0.0-rc.1 - Database: a Amazon DynamoDB, or DynamoDB Local for development (tested with DynamoDB Local 2.5.2) database with the sample schema.
- Configuration: set
ARX_SAMPLES_DYNAMODBto 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,SampleModel.cs,SampleContext.Direct.cs,DynamoDirectHelper.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 and first remakes the sample database from sample-schema.json.
using ArxSamples.DynamoDb;
using ArxSamples.DynamoDb.Operations.Create.Basics;
// The connection string comes from the environment, never from the code (see "Configure the connection").
var connectionString = Environment.GetEnvironmentVariable("ARX_SAMPLES_DYNAMODB")
?? throw new InvalidOperationException("Set the ARX_SAMPLES_DYNAMODB environment variable to your Amazon DynamoDB connection string.");
var dbContext = new SampleContext(connectionString);
// Every run starts from the sample data: this deletes and makes again what sample-schema.json lists
// (save the file in the project folder, see Get started).
await dbContext.Direct.ResetAsync();
await new Basic2_CatchAnError().RunAsync(dbContext);
The sample, as it is in the repository.
using Amazon.DynamoDBv2;
using ARX.SDK;
using ARX.SDK.DynamoDb.Model;
using ARX.SDK.DynamoDb.Services;
using ARX.SDK.Services;
using static ArxSamples.DynamoDb.SampleOutput;
namespace ArxSamples.DynamoDb.Operations.Create.Basics;
/// <summary>
/// The errors a create meets most, in three scenarios: a key that exists, a key attribute left out, and an id declared
/// as generated, which DynamoDB can't do.
/// </summary>
public sealed class Basic2_CatchAnError : ISample
{
public string Name => "create-basics-2-catch-an-error";
public string Title => "Catch the errors a create meets";
public async Task RunAsync(SampleContext dbContext)
{
await Scenario1_AKeyThatExistsAsync(dbContext.Service);
await Scenario2_AKeyAttributeLeftOutAsync(dbContext.Service);
await Scenario3_AGeneratedIdAsync(dbContext.Client);
}
/// <summary>1. The same customer twice: ARX3001; the first stays as it was.</summary>
private static async Task Scenario1_AKeyThatExistsAsync(ArxDynamoDbService service)
{
Step("1. A key that exists");
var customer = new ArxEntity("customer");
customer["customer_id"] = "C-D401";
customer["name"] = "Fabrikam";
await service.CreateAsync(customer);
customer["name"] = "Fabrikam (copy)";
try
{
await service.CreateAsync(customer);
}
catch (ArxDatabaseException exception) when (exception.Code == ArxErrorCode.UniqueViolation)
{
ShowError(exception);
}
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT "name" FROM "crm" WHERE "PK" = 'CUSTOMER#C-D401' AND "SK" = 'PROFILE'
* -- Expect: 1 item, name "Fabrikam".
* ===========================================================
*/
}
/// <summary>2. An order without its customer_id: its key can't be made, so nothing is sent.</summary>
private static async Task Scenario2_AKeyAttributeLeftOutAsync(ArxDynamoDbService service)
{
Step("2. A key attribute left out");
var order = new ArxEntity("sales_order");
order["order_number"] = "SO-D402";
try
{
await service.CreateAsync(order);
}
catch (ArxValidationException exception)
{
ShowError(exception);
}
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT "SK" FROM "crm" WHERE "SK" = 'ORDER#SO-D402'
* -- Expect: no items.
* ===========================================================
*/
}
/// <summary>3. An id declared as generated: DynamoDB generates nothing, so ARX8001 with the advice to supply one.</summary>
private static async Task Scenario3_AGeneratedIdAsync(IAmazonDynamoDB client)
{
Step("3. A generated id");
var catalog = ArxSchemaCatalog.Create().Table("product", ArxIdColumn.Generated<string>("sku")).Build();
var service = new ArxDynamoDbService(client, ArxDynamoModel.Create().Table("product", partitionKey: "sku").Build(), catalog);
var product = new ArxEntity("product");
product["sku"] = "SKU-D403";
try
{
await service.CreateAsync(product);
}
catch (ArxNotSupportedException exception)
{
ShowError(exception);
}
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT "sku" FROM "product" WHERE "sku" = 'SKU-D403'
* -- Expect: no items.
* ===========================================================
*/
}
}
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. A key that exists
caught ArxDatabaseException: ARX3001 UniqueViolation: Create of 'customer': an item with the same key already exists.
> 2. A key attribute left out
caught ArxValidationException: ARX1001 InvalidArgument: 'sales_order' needs 'customer_id' for its key (customer_id, order_number).
> 3. A generated id
caught ArxNotSupportedException: ARX8001 NotSupported: 'product' declares id 'sku' as generated, and DynamoDB generates no ids. Give the id yourself and declare it ArxIdColumn.Supplied<String>("sku"), with a value such as Guid.CreateVersion7().