C# AWS DynamoDB:删除项目并将其放入同一事务中

问题描述 投票:0回答:1

在我的 API 中,我使用测试。测试可以包含问题,问题可以包含答案和图像。

以最简单的方式更新项目我删除测试+问题+答案+图像,然后在同一交易中使用新值再次“放置”它们。

这样做我收到一个

"Transaction request cannot include multiple operations on one item"

异常。

CreateTestAsync

public async Task<int> CreateTestAsync(TestDTO testDto, int saveMode) { if (testDto.Questions == null) return Result.KO; try { //save test data //var table = Table.LoadTable(_client, Tables.Tests.TableName); transactionActions = new List<TransactWriteItem>(); //delete items first if (saveMode == SaveMode.Update) { Delete delete; Dictionary<string, AttributeValue> key; if (testDto.Questions != null) { foreach (var question in testDto.Questions) { if (question.Answers != null) { foreach (var answer in question.Answers) { //delete answer delete = DeleteElementAsync1(Tables.Answers.TableName, Tables.Answers.Fields.Id, answer.Id); transactionActions.Add(new TransactWriteItem { Delete = delete }); } } if (question.Images != null) { foreach (var image in question.Images) { //delete image delete = DeleteElementAsync1(Tables.Images.TableName, Tables.Images.Fields.Id, image.Id); transactionActions.Add(new TransactWriteItem { Delete = delete }); //delete image from S3 } } //delete question delete = DeleteElementAsync1(Tables.Questions.TableName, Tables.Questions.Fields.Id, question.Id); transactionActions.Add(new TransactWriteItem { Delete = delete }); } } //delete test delete = DeleteElementAsync1(Tables.Tests.TableName, Tables.Tests.Fields.Id, testDto.Id); transactionActions.Add(new TransactWriteItem { Delete = delete }); } //save test var json = JsonConvert.SerializeObject(testDto); var document = Document.FromJson(json); document.Remove("Questions"); var testTable = Table.LoadTable(_client, Tables.Tests.TableName); var put = GeneratePutAsync(document, testTable, Tables.Tests.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); //save items then if (testDto.Questions != null && testDto.Questions.Any()) { //save questions var questionsTable = Table.LoadTable(_client, Tables.Questions.TableName); foreach (var question in testDto.Questions) { json = JsonConvert.SerializeObject(question); document = Document.FromJson(json); document.Remove("Answers"); document.Remove("Images"); put = GeneratePutAsync(document, questionsTable, Tables.Questions.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); if (question.Answers != null && question.Answers.Any()) { var answersTable = Table.LoadTable(_client, Tables.Answers.TableName); foreach (var answer in question.Answers) { json = JsonConvert.SerializeObject(answer); document = Document.FromJson(json); put = GeneratePutAsync(document, answersTable, Tables.Answers.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); } } if (question.Images != null && question.Images.Any()) { var imagesTable = Table.LoadTable(_client, Tables.Images.TableName); foreach (var image in question.Images) { json = JsonConvert.SerializeObject(image); document = Document.FromJson(json); put = GeneratePutAsync(document, imagesTable, Tables.Images.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); } } } } var transactionResult = await RunTransaction(transactionActions); return Result.OK; } catch (Exception e) { return Result.KO; } }

RunTransactions

private async Task<int> RunTransaction(List<TransactWriteItem> actions) { var transaction = new TransactWriteItemsRequest() { TransactItems = actions, ReturnConsumedCapacity = ReturnConsumedCapacity.TOTAL }; // Run the transaction and process the result. try { var transactionResult = await _client.TransactWriteItemsAsync(transaction); Console.WriteLine("Transaction Successful"); return Result.OK; } catch (ResourceNotFoundException rnf) { Console.Error.WriteLine("One of the table involved in the transaction is not found" + rnf.Message); return Result.KO; } catch (InternalServerErrorException ise) { Console.Error.WriteLine("Internal Server Error" + ise.Message); return Result.KO; } catch (TransactionCanceledException tce) { Console.Error.WriteLine("Transaction Canceled " + tce.Message); return Result.KO; } catch (Exception tce) { Console.Error.WriteLine("General error: " + tce.Message); return Result.KO; } }
确实,我在同一个元素中包含了多个操作(在我的例子中为“Delete + Put”),但我必须这样做。此外,它们是

不同的操作。

我检查了这个

交易请求不能包含对一个项目python的多个操作,但它不包含解决方案。

我知道最好是进行更新而不是删除+插入,问题是如果我要更新或插入,我需要检查每个问题、答案和图像,这可能会使我的代码更加复杂。

有什么解决办法吗?

c# transactions amazon-dynamodb
1个回答
0
投票
进行更深入的研究,我发现“PutItem”操作也可以进行更新(如果分区键已经存在)。最后,这意味着在不修改代码的情况下,我可以跳过初始的“删除”操作,只需执行“放置”操作即可完成工作事务。

工作解决方案:

public async Task<int> CreateTestAsync(TestDTO testDto) { if (testDto.Questions == null) return Result.KO; try { //save test data transactionActions = new List<TransactWriteItem>(); //save test var json = JsonConvert.SerializeObject(testDto); var document = Document.FromJson(json); document.Remove("Questions"); var testTable = Table.LoadTable(_client, Tables.Tests.TableName); var put = GeneratePutAsync(document, testTable, Tables.Tests.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); //save items then if (testDto.Questions != null && testDto.Questions.Any()) { //save questions var questionsTable = Table.LoadTable(_client, Tables.Questions.TableName); foreach (var question in testDto.Questions) { json = JsonConvert.SerializeObject(question); document = Document.FromJson(json); document.Remove("Answers"); document.Remove("Images"); put = GeneratePutAsync(document, questionsTable, Tables.Questions.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); if (question.Answers != null && question.Answers.Any()) { var answersTable = Table.LoadTable(_client, Tables.Answers.TableName); foreach (var answer in question.Answers) { json = JsonConvert.SerializeObject(answer); document = Document.FromJson(json); put = GeneratePutAsync(document, answersTable, Tables.Answers.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); } } if (question.Images != null && question.Images.Any()) { var imagesTable = Table.LoadTable(_client, Tables.Images.TableName); foreach (var image in question.Images) { json = JsonConvert.SerializeObject(image); document = Document.FromJson(json); put = GeneratePutAsync(document, imagesTable, Tables.Images.Fields.Id); transactionActions.Add(new TransactWriteItem { Put = put }); } } } } var transactionResult = await RunTransaction(transactionActions); return Result.OK; } catch (Exception e) { return Result.KO; } }
“RunTransaction”方法保持完整,如原始问题中所示。

© www.soinside.com 2019 - 2024. All rights reserved.