DynamoDBv2.Transactions
3.7.30326.189
dotnet add package DynamoDBv2.Transactions --version 3.7.30326.189
NuGet\Install-Package DynamoDBv2.Transactions -Version 3.7.30326.189
<PackageReference Include="DynamoDBv2.Transactions" Version="3.7.30326.189" />
paket add DynamoDBv2.Transactions --version 3.7.30326.189
#r "nuget: DynamoDBv2.Transactions, 3.7.30326.189"
// Install DynamoDBv2.Transactions as a Cake Addin #addin nuget:?package=DynamoDBv2.Transactions&version=3.7.30326.189 // Install DynamoDBv2.Transactions as a Cake Tool #tool nuget:?package=DynamoDBv2.Transactions&version=3.7.30326.189
DynamoDBv2.Transactions
DynamoDBv2.Transactions is a .NET library that provides a robust wrapper around the Amazon DynamoDB low-level API, enabling easy and efficient management of transactions for batch operations. This library is designed to simplify complex transactional logic and ensure data consistency across your DynamoDB operations. It skips additional implicit for some cases DescribeTable call, thus making DynamoDB attributes mandatory - alternatively too using the attributes you can provide KeyName/KeyValue as a separate parameter to a method.
• Source Link: ✅ Valid with Symbol Server • Deterministic (dll/exe): ✅ Valid • Compiler Flags: ✅ Valid
Features
- Transactional Operations: Supports
CreateOrUpdate
,Delete
, andUpdate
andConditionCheck
operations within transactions. - Error Handling: Gracefully handles transaction failures and rollbacks.
- Versioning Support: Automatic handling of version increments for transactional integrity.
- Easy Integration: Seamlessly integrates with existing DynamoDB setups.
- Asynchronous API: Fully asynchronous API for optimal performance.
Plans
- Add Source Generator in order to validate abscence of [DynamoDBHashKey("UserId")] attribute
- Write more tests on SortKey
- Write more benchmarks.
Installation
You can install the DynamoDBv2.Transactions library via NuGet Package Manager. Run the following command in your Package Manager Console:
Install-Package DynamoDBv2.Transactions
Quick Start
To get started with DynamoDBv2.Transactions, you'll need to set up an instance of TransactionalWriter
using an ITransactionManager
, which is responsible for executing the transactions against your DynamoDB instance.
Prerequisites
Ensure you have the AWS SDK for .NET configured in your project, with access to Amazon DynamoDB.
Example Usage
!!! It skips additional implicit for some cases DescribeTable call, thus making DynamoDB attribute [DynamoDBHashKey("YourId")] mandatory !!!
Which makes it faster in comparison with the traditional wrapper.
Here's a quick example to show you how to use the TransactionalWriter
to perform a transaction:
using DynamoDBv2.Transactions;
// Initialize the DynamoDB client
var client = new AmazonDynamoDBClient();
// Setup transaction manager and writer
var transactionManager = new TransactionManager(client);
var writer = new TransactionalWriter(transactionManager);
var userId = Guid.NewGuid().ToString();
var testItem = new TestTable
{
UserId = userId,
SomeDecimal = 123.45m,
SomeDate = DateTime.UtcNow,
SomeInt = 123
};
// Perform transaction
await using (writer)
{
writer.CreateOrUpdate(testItem);
}
// Load and verify
var dbContext = new DynamoDBContext(client);
var data = await dbContext.LoadAsync<TestTable>(userId);
Console.WriteLine($"Item saved with UserId: {data.UserId}");
Deleting an Item
// Arrange
var userIdToDelete = "unique-user-id";
// Act
await using (var transactor = new DynamoDbTransactor(_fixture.Db.Client))
{
transactor.DeleteAsync<TestTable>(userIdToDelete);
};
// This operation will asynchronously delete the specified item from DynamoDB.
Patching an Item
// Arrange
var userIdToPatch = "unique-user-id";
var updatedDate = DateTime.UtcNow.AddDays(1);
// Act
await using (var transactor = new DynamoDbTransactor(_fixture.Db.Client))
{
transactor.PatchAsync<TestTable, DateTime?>(userIdToPatch, t => t.SomeNullableDate1, updatedDate);
};
// This code patches the 'SomeNullableDate1' property of the specified item to a new date.
Adding a conditional check
// Arrange
var userIdToCheck = "unique-user-id";
// Act
await using (var transactor = new DynamoDbTransactor(_fixture.Db.Client))
{
transactor.ConditionGreaterThan<TestTable, int>(userIdToCheck, t => t.SomeInt, 100);
transactor.CreateOrUpdate(new TestTable { UserId = userIdToCheck, SomeInt = 200 });
};
// This will add a conditional check to ensure 'SomeInt' is greater than 100 before updating or creating the item.
Complex Transaction with Multiple Operations
// Arrange
var userId = Guid.NewGuid().ToString();
var testItem = new TestTable
{
UserId = userId,
SomeInt = 150,
SomeDate = DateTime.UtcNow,
SomeBool = true
};
// Act
await using (var transactor = new DynamoDbTransactor(_fixture.Db.Client))
{
transactor.ConditionNotEquals<TestTable, bool>(userId, t => t.SomeBool, false);
transactor.CreateOrUpdate(testItem);
transactor.PatchAsync<TestTable, int>(userId, t => t.SomeInt, 200);
};
// This transaction will check if 'SomeBool' is not false, then create or update the item, and finally patch 'SomeInt' to 200.
Version Check Before Update
// Arrange
var userId = Guid.NewGuid().ToString();
var expectedVersion = 1;
// Act
await using (var transactor = new DynamoDbTransactor(_fixture.Db.Client))
{
transactor.ConditionVersionEquals<TestTable>(userId, t => t.Version, expectedVersion);
transactor.CreateOrUpdate(new TestTable { UserId = userId, SomeInt = 250 });
};
// This ensures the item's version matches the expected version before it is updated or created.
BenchmarkDotNet results
// * Summary *
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3527/23H2/2023Update/SunValley3) AMD Ryzen 9 6900HS with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores .NET SDK 8.0.200 [Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2 OutOfProc : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
Job=OutOfProc IterationCount=15 LaunchCount=3 WarmupCount=10
Method | Mean | Error | StdDev | Allocated |
---|---|---|---|---|
DynamoDbTransactionsWrapper | 11.99 ms | 0.046 ms | 0.087 ms | 80.96 KB |
OriginalWrapper | 15.83 ms | 0.236 ms | 0.442 ms | 83.77 KB |
DynamoDbTransactionsWrapper3Items | 13.37 ms | 0.066 ms | 0.123 ms | 114.74 KB |
OriginalWrapper3Items | 46.44 ms | 0.444 ms | 0.834 ms | 251.01 KB |
// * Hints * Outliers Benchmark.DynamoDbTransactionsWrapper3Items: OutOfProc → 3 outliers were removed (13.64 ms..14.81 ms) Benchmark.OriginalWrapper3Items: OutOfProc → 3 outliers were removed (48.78 ms..49.19 ms)
// * Legends * Mean : Arithmetic mean of all measurements Error : Half of 99.9% confidence interval StdDev : Standard deviation of all measurements Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B) 1 ms : 1 Millisecond (0.001 sec)
// * Diagnostic Output - MemoryDiagnoser *
// ***** BenchmarkRunner: End ***** Run time: 00:04:09 (249.42 sec), executed benchmarks: 4
To run benchmark:
- Goto .\DynamoDBv2.Transactions
- dotnet build .\test\DynamoDBv2.Transactions.Benchmarks\ -c Release
- Execute in shell .\test\DynamoDBv2.Transactions.Benchmarks\bin\Release\net8.0\DynamoDBv2.Transactions.exe
Running Tests
To run integration tests
ensure you have a test instance of DynamoDB available. (and configure it in env of the docker compose file) (On my env tests are running both in real DynamoDB and localstack instance) Tests are written using xUnit and should be configured to interact directly with your database:
- docker-compose up --exit-code-from tests tests localstack
- docker-compose up --exit-code-from unittests unittests
// Example test
[Fact]
public async Task SaveDataAndRetrieve()
{
var writer = new TransactionalWriter(new TransactionManager(_fixture.Db.Client));
var userId = Guid.NewGuid().ToString();
var testItem = new TestTable
{
UserId = userId,
SomeInt = 123
};
await using (var writer = new TransactionalWriter(new TransactionManager(_fixture.Db.Client)))
{
writer.CreateOrUpdate(testItem);
}
var retrievedItem = await _fixture.Db.Context.LoadAsync<TestTable>(userId);
Assert.NotNull(retrievedItem);
}
Contributing
When creating PRs, please review the following guidelines:
- The action code does not contain sensitive information.
- At least one of the commit messages contains the appropriate
+semver:
keywords listed under [Incrementing the Version] for major and minor increments. - The action has been recompiled. See [Recompiling Manually] for details.
- The README.md has been updated with the latest version of the action. See [Updating the README.md] for details.
License
Copyright © 2024, Vitali Bibikov. Code released under the MIT license.
Contact
Your Name - [bibikovvitaly@gmail.com]
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.7.30326.189 | 207 | 6/27/2024 |
3.7.30322.183 | 226 | 6/18/2024 |
3.7.30312.170 | 114 | 5/28/2024 |
3.7.30226.96-beta | 50 | 5/2/2024 |
3.7.30215.92-beta | 86 | 5/1/2024 |
3.7.30215.90-beta | 85 | 5/1/2024 |
3.7.30215.86-beta | 81 | 5/1/2024 |
3.7.30215.83-beta | 79 | 5/1/2024 |
3.7.30215.82-beta | 68 | 5/1/2024 |
3.7.3051.209 | 116 | 7/20/2024 |
3.7.3043.197 | 102 | 7/8/2024 |
3.7.3042.194 | 97 | 7/4/2024 |
3.7.3036.156 | 116 | 5/15/2024 |
3.7.3031.148 | 127 | 5/4/2024 |
3.7.3031.146-beta | 87 | 5/4/2024 |