From a69178b10fc8f43ae2cf876556062e54820f35ef Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Wed, 14 Aug 2024 16:52:15 -0700
Subject: [PATCH 1/7] Add the ability to mock DocumentBatchGet and
MultiTableDocumentBatchGet operations
---
.../Custom/DocumentModel/DocumentBatchGet.cs | 157 ++++++++++++------
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 2 +-
.../_async/DocumentBatchGet.Async.cs | 37 ++---
.../_bcl/DocumentBatchGet.Sync.cs | 39 ++---
.../MockabilityTests/DocumentBatchGetTests.cs | 151 +++++++++++++++++
5 files changed, 285 insertions(+), 101 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
index bcec76d707f6..8a9e84060940 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
@@ -21,14 +21,70 @@
using System.Threading.Tasks;
#endif
using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
namespace Amazon.DynamoDBv2.DocumentModel
{
+ ///
+ /// Interface for retrieving a batch of Documents from a single DynamoDB table.
+ ///
+ public partial interface IDocumentBatchGet
+ {
+ ///
+ /// List of results retrieved from DynamoDB.
+ /// Populated after Execute is called.
+ ///
+ public List Results { get; }
+
+ ///
+ /// List of attributes to retrieve.
+ ///
+ public List AttributesToGet { get; set; }
+
+ ///
+ /// Returns the total number of keys associated with this Batch request.
+ ///
+ public int TotalKeys { get; }
+
+ ///
+ /// If set to true, a consistent read is issued. Otherwise eventually-consistent is used.
+ ///
+ public bool ConsistentRead { get; set; }
+
+ ///
+ /// Add a single item to get, identified by its hash primary key.
+ ///
+ /// Hash key element of the item to get.
+ void AddKey(Primitive hashKey);
+
+ ///
+ /// Add a single item to get, identified by its hash-and-range primary key.
+ ///
+ /// Hash key element of the item to get.
+ /// Range key element of the item to get.
+ void AddKey(Primitive hashKey, Primitive rangeKey);
+
+ ///
+ /// Add a single item to get, identified by its key.
+ ///
+ /// Key of the item to get.
+ void AddKey(IDictionary key);
+
+ ///
+ /// Creates a MultiTableDocumentBatchGet object that is a combination
+ /// of the current DocumentBatchGet and the specified DocumentBatchGet.
+ ///
+ /// Other DocumentBatchGet object.
+ ///
+ /// MultiTableDocumentBatchGet consisting of the two DocumentBatchGet
+ /// objects.
+ ///
+ MultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch);
+ }
+
///
/// Class for retrieving a batch of Documents from a single DynamoDB table.
///
- public partial class DocumentBatchGet
+ public partial class DocumentBatchGet : IDocumentBatchGet
{
#region Internal properties
@@ -40,20 +96,16 @@ public partial class DocumentBatchGet
#region Public properties
- ///
- /// List of results retrieved from DynamoDB.
- /// Populated after Execute is called.
- ///
+ ///
public List Results { get; internal set; }
- ///
- /// List of attributes to retrieve.
- ///
+ ///
public List AttributesToGet { get; set; }
- ///
- /// If set to true, a consistent read is issued. Otherwise eventually-consistent is used.
- ///
+ ///
+ public int TotalKeys => Keys.Count;
+
+ ///
public bool ConsistentRead { get; set; }
#endregion
@@ -76,44 +128,26 @@ public DocumentBatchGet(Table targetTable)
#region Public methods
- ///
- /// Add a single item to get, identified by its hash primary key.
- ///
- /// Hash key element of the item to get.
+ ///
public void AddKey(Primitive hashKey)
{
AddKey(hashKey, null);
}
- ///
- /// Add a single item to get, identified by its hash-and-range primary key.
- ///
- /// Hash key element of the item to get.
- /// Range key element of the item to get.
+ ///
public void AddKey(Primitive hashKey, Primitive rangeKey)
{
Keys.Add(TargetTable.MakeKey(hashKey, rangeKey));
}
- ///
- /// Add a single item to get, identified by its key.
- ///
- /// Key of the item to get.
+ ///
public void AddKey(IDictionary key)
{
Keys.Add(TargetTable.MakeKey(key));
}
- ///
- /// Creates a MultiTableDocumentBatchGet object that is a combination
- /// of the current DocumentBatchGet and the specified DocumentBatchGet.
- ///
- /// Other DocumentBatchGet object.
- ///
- /// MultiTableDocumentBatchGet consisting of the two DocumentBatchGet
- /// objects.
- ///
- public MultiTableDocumentBatchGet Combine(DocumentBatchGet otherBatch)
+ ///
+ public MultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch)
{
return new MultiTableDocumentBatchGet(this, otherBatch);
}
@@ -179,21 +213,39 @@ internal void AddKey(Key key)
}
///
- /// Class for retrieving a batch of Documents from multiple DynamoDB tables.
+ /// Interface for retrieving a batch of Documents from multiple DynamoDB tables.
///
- public partial class MultiTableDocumentBatchGet
+ public partial interface IMultiTableDocumentBatchGet
{
- #region Properties
-
///
/// List of DocumentBatchGet objects to include in the multi-table
/// batch request.
///
- public List Batches { get; private set; }
+ public List Batches { get; }
///
/// Total number of primary keys in the multi-table batch request.
///
+ public int TotalKeys { get; }
+
+ ///
+ /// Add a DocumentBatchGet object to the multi-table batch request.
+ ///
+ /// DocumentBatchGet to add.
+ void AddBatch(IDocumentBatchGet batch);
+ }
+
+ ///
+ /// Class for retrieving a batch of Documents from multiple DynamoDB tables.
+ ///
+ public partial class MultiTableDocumentBatchGet : IMultiTableDocumentBatchGet
+ {
+ #region Properties
+
+ ///
+ public List Batches { get; private set; }
+
+ ///
public int TotalKeys
{
get
@@ -201,7 +253,7 @@ public int TotalKeys
int count = 0;
foreach (var batch in Batches)
{
- count += batch.Keys.Count;
+ count += batch.TotalKeys;
}
return count;
}
@@ -217,12 +269,12 @@ public int TotalKeys
/// DocumentBatchGet objects.
///
/// Collection of DocumentBatchGet objects.
- public MultiTableDocumentBatchGet(params DocumentBatchGet[] batches)
+ public MultiTableDocumentBatchGet(params IDocumentBatchGet[] batches)
{
if (batches == null)
throw new ArgumentNullException("batches");
- Batches = new List(batches);
+ Batches = new List(batches);
}
#endregion
@@ -230,11 +282,8 @@ public MultiTableDocumentBatchGet(params DocumentBatchGet[] batches)
#region Public methods
- ///
- /// Add a DocumentBatchGet object to the multi-table batch request.
- ///
- /// DocumentBatchGet to add.
- public void AddBatch(DocumentBatchGet batch)
+ ///
+ public void AddBatch(IDocumentBatchGet batch)
{
Batches.Add(batch);
}
@@ -245,14 +294,16 @@ public void AddBatch(DocumentBatchGet batch)
internal void ExecuteHelper()
{
+ var errMsg = $"All {nameof(IDocumentBatchGet)} objects must be of type {nameof(DocumentBatchGet)}";
+ var docBatches = Batches.Select( x => x as DocumentBatchGet ?? throw new InvalidOperationException(errMsg)).ToList();
MultiBatchGet resultsObject = new MultiBatchGet
{
- Batches = Batches
+ Batches = docBatches
};
var results = resultsObject.GetItemsHelper();
- foreach (var batch in Batches)
+ foreach (var batch in docBatches)
{
List batchResults;
if (results.TryGetValue(batch.TargetTable.TableName, out batchResults))
@@ -269,14 +320,16 @@ internal void ExecuteHelper()
#if AWS_ASYNC_API
internal async Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
+ var errMsg = $"All {nameof(IDocumentBatchGet)} objects must be of type {nameof(DocumentBatchGet)}";
+ var docBatches = Batches.Select(x => x as DocumentBatchGet ?? throw new InvalidOperationException(errMsg)).ToList();
MultiBatchGet resultsObject = new MultiBatchGet
{
- Batches = Batches
+ Batches = docBatches
};
var results = await resultsObject.GetItemsHelperAsync(cancellationToken).ConfigureAwait(false);
- foreach (var batch in Batches)
+ foreach (var batch in docBatches)
{
List batchResults;
if (results.TryGetValue(batch.TargetTable.TableName, out batchResults))
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index 6a30637db5f6..5316f29ab66a 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -1560,7 +1560,7 @@ public Search Query(QueryOperationConfig config)
/// a batch-get operation against DynamoDB.
///
/// Empty DocumentBatchGet object.
- public DocumentBatchGet CreateBatchGet()
+ public IDocumentBatchGet CreateBatchGet()
{
return new DocumentBatchGet(this);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchGet.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchGet.Async.cs
index d3b0665a0fe2..a0ef642ab898 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchGet.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchGet.Async.cs
@@ -14,57 +14,48 @@
*/
#pragma warning disable 1574
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-using Amazon.Runtime.Internal;
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for retrieving a batch of Documents from a single DynamoDB table.
- ///
- public partial class DocumentBatchGet
+ public partial interface IDocumentBatchGet
{
- #region Public methods
-
///
/// Executes a server call to batch-get the documents requested.
/// Populates Results with the retrieved items.
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class DocumentBatchGet : IDocumentBatchGet
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
- ///
- /// Class for retrieving a batch of Documents from multiple DynamoDB tables.
- ///
- public partial class MultiTableDocumentBatchGet
+ public partial interface IMultiTableDocumentBatchGet
{
- #region Public methods
-
///
/// Executes a multi-table batch request against all configured batches.
/// Results are stored in the respective DocumentBatchGet objects.
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class MultiTableDocumentBatchGet : IMultiTableDocumentBatchGet
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
-
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
index 8059a3861fa1..1b68f7ab14bc 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
@@ -13,52 +13,41 @@
* permissions and limitations under the License.
*/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for retrieving a batch of Documents from a single DynamoDB table.
- ///
- public partial class DocumentBatchGet
+ public partial interface IDocumentBatchGet
{
-
- #region Public methods
-
///
/// Executes a server call to batch-get the documents requested.
/// Populates Results with the retrieved items.
///
+ void Execute();
+ }
+
+ public partial class DocumentBatchGet : IDocumentBatchGet
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
-
}
- ///
- /// Class for retrieving a batch of Documents from multiple DynamoDB tables.
- ///
- public partial class MultiTableDocumentBatchGet
+ public partial interface IMultiTableDocumentBatchGet
{
- #region Public methods
-
///
/// Executes a multi-table batch request against all configured batches.
/// Results are stored in the respective DocumentBatchGet objects.
///
+ void Execute();
+ }
+
+ public partial class MultiTableDocumentBatchGet
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
}
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs
new file mode 100644
index 000000000000..0fc589a72623
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs
@@ -0,0 +1,151 @@
+using Amazon.DynamoDBv2.DocumentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class DocumentBatchGetTests
+ {
+ [TestMethod]
+ public void TestMockability_DocumentBatchGet()
+ {
+ var dummyResults = new List()
+ {
+ new Document()
+ {
+ {"State", "CA"},
+ {"Zip", "12345"}
+ }
+ };
+
+ var docBatchGet = CreateDocumentBatchGetMock(dummyResults);
+
+ Assert.AreEqual(0, docBatchGet.TotalKeys);
+ Assert.AreEqual(0, docBatchGet.Results.Count);
+
+ docBatchGet.AddKey("State");
+ Assert.AreEqual(1, docBatchGet.TotalKeys);
+
+ docBatchGet.Execute();
+ Assert.AreEqual(1, docBatchGet.Results.Count);
+ Assert.AreEqual("CA", docBatchGet.Results[0]["State"].AsString());
+ Assert.AreEqual("12345", docBatchGet.Results[0]["Zip"].AsString());
+ }
+
+ [TestMethod]
+ public void TestMockability_MultiTableDocumentBatchGet()
+ {
+ var addressBatchGet = CreateDocumentBatchGetMock(new List
+ {
+ new Document()
+ {
+ {"State", "CA"},
+ {"Zip", "12345"}
+ }
+ });
+
+ var personBatchGet = CreateDocumentBatchGetMock(new List
+ {
+ new Document()
+ {
+ {"FirstName", "John"},
+ {"LastName", "Doe"}
+ }
+ });
+
+ var multiBatchGet = CreateMultiTableDocumentBatchGetMock();
+ multiBatchGet.AddBatch(addressBatchGet);
+ multiBatchGet.AddBatch(personBatchGet);
+
+ Assert.AreEqual(0, multiBatchGet.TotalKeys);
+ Assert.AreEqual(0, addressBatchGet.Results.Count);
+ Assert.AreEqual(0, personBatchGet.Results.Count);
+
+ addressBatchGet.AddKey("CA");
+ personBatchGet.AddKey("John");
+ Assert.AreEqual(2, multiBatchGet.TotalKeys);
+
+ multiBatchGet.Execute();
+
+ Assert.AreEqual(1, addressBatchGet.Results.Count);
+ Assert.AreEqual("CA", addressBatchGet.Results[0]["State"].AsString());
+ Assert.AreEqual("12345", addressBatchGet.Results[0]["Zip"].AsString());
+
+ Assert.AreEqual(1, personBatchGet.Results.Count);
+ Assert.AreEqual("John", personBatchGet.Results[0]["FirstName"].AsString());
+ Assert.AreEqual("Doe", personBatchGet.Results[0]["LastName"].AsString());
+ }
+
+ public IDocumentBatchGet CreateDocumentBatchGetMock(List results)
+ {
+ var documentBatchGet = new Mock();
+ var dummyResults = new List();
+ var keys = new List();
+
+ documentBatchGet
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ dummyResults.Clear();
+ dummyResults.AddRange(results);
+ });
+
+ documentBatchGet
+ .Setup(x => x.Results)
+ .Returns(dummyResults);
+
+ documentBatchGet
+ .Setup(x => x.AddKey(It.IsAny()))
+ .Callback((Primitive hashKey) =>
+ {
+ keys.Add(hashKey.AsString());
+ });
+
+ documentBatchGet
+ .SetupGet(x => x.TotalKeys)
+ .Returns(() => keys.Count);
+
+ return documentBatchGet.Object;
+ }
+
+ public IMultiTableDocumentBatchGet CreateMultiTableDocumentBatchGetMock()
+ {
+ var multiBatchGet = new Mock();
+ var batches = new List();
+
+ multiBatchGet
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var batch in batches)
+ {
+ batch.Execute();
+ }
+ });
+
+ multiBatchGet
+ .Setup(x => x.AddBatch(It.IsAny()))
+ .Callback((IDocumentBatchGet batch) =>
+ {
+ batches.Add(batch);
+ });
+
+ multiBatchGet.
+ SetupGet(x => x.TotalKeys)
+ .Returns(() =>
+ {
+ var totalKeys = 0;
+ foreach (var batch in batches)
+ {
+ totalKeys += batch.TotalKeys;
+ }
+ return totalKeys;
+ });
+
+
+ return multiBatchGet.Object;
+ }
+ }
+}
From a1965dfddc36bcf634e82b6fb677dfc1623acecf Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Wed, 14 Aug 2024 18:28:03 -0700
Subject: [PATCH 2/7] Add the ability to mock DocumentBatchWrite and
MultiTableDocumentBatchWrite operations
---
.../DynamoDBv2/Custom/DataModel/BatchWrite.cs | 5 +-
.../DocumentModel/DocumentBatchWrite.cs | 133 +++++++++++-------
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 2 +-
.../_async/DocumentBatchWrite.Async.cs | 37 ++---
.../_bcl/DocumentBatchWrite.Sync.cs | 39 ++---
.../DocumentBatchWriteTests.cs | 114 +++++++++++++++
6 files changed, 233 insertions(+), 97 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
index 8c45afba89ea..4f773862f684 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
@@ -128,7 +128,10 @@ internal BatchWrite(DynamoDBContext context, Type valuesType, DynamoDBFlatConfig
}
Table table = _context.GetTargetTable(_storageConfig, _config);
- DocumentBatch = table.CreateBatchWrite();
+
+ // Table.CreateBatchWrite() returns the IDocumentBatchWrite interface.
+ // But since we rely on the internal behavior of DocumentBatchWrite, we instantiate it via the constructor.
+ DocumentBatch = new DocumentBatchWrite(table);
}
///
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
index 2d4a4e882928..4557db28b48f 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
@@ -15,21 +15,68 @@
using System;
using System.Collections.Generic;
-using System.IO;
+using System.Linq;
using System.Net;
using System.Threading;
#if AWS_ASYNC_API
using System.Threading.Tasks;
#endif
using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
namespace Amazon.DynamoDBv2.DocumentModel
{
+ ///
+ /// Interface for putting and/or deleting a batch of items in a single DynamoDB table.
+ ///
+ public partial interface IDocumentBatchWrite
+ {
+ ///
+ /// Add a single item to delete, identified by its hash primary key.
+ ///
+ /// Hash key element of the item to delete.
+ void AddKeyToDelete(Primitive hashKey);
+
+ ///
+ /// Add a single item to delete, identified by its hash-and-range primary key.
+ ///
+ /// Hash key element of the item to delete.
+ /// Range key element of the item to delete.
+ void AddKeyToDelete(Primitive hashKey, Primitive rangeKey);
+
+ ///
+ /// Add a single item to delete, identified by its key.
+ ///
+ /// Key of the item to delete.
+ void AddKeyToDelete(IDictionary key);
+
+ ///
+ /// Add a single item to delete, identified by a Document object.
+ ///
+ /// Document representing the item to be deleted.
+ public void AddItemToDelete(Document document);
+
+ ///
+ /// Add a single Document to put.
+ ///
+ /// Document to put.
+ void AddDocumentToPut(Document document);
+
+ ///
+ /// Creates a MultiTableDocumentBatchWrite object that is a combination
+ /// of the current DocumentBatchWrite and the specified DocumentBatchWrite.
+ ///
+ /// Other DocumentBatchWrite object.
+ ///
+ /// MultiTableDocumentBatchWrite consisting of the two DocumentBatchWrite
+ /// objects.
+ ///
+ MultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch);
+ }
+
///
/// Class for putting and/or deleting a batch of items in a single DynamoDB table.
///
- public partial class DocumentBatchWrite
+ public partial class DocumentBatchWrite : IDocumentBatchWrite
{
#region Internal properties
@@ -58,38 +105,25 @@ public DocumentBatchWrite(Table targetTable)
#region Public Delete methods
- ///
- /// Add a single item to delete, identified by its hash primary key.
- ///
- /// Hash key element of the item to delete.
+ ///
public void AddKeyToDelete(Primitive hashKey)
{
AddKeyToDelete(hashKey, null);
}
- ///
- /// Add a single item to delete, identified by its hash-and-range primary key.
- ///
- /// Hash key element of the item to delete.
- /// Range key element of the item to delete.
+ ///
public void AddKeyToDelete(Primitive hashKey, Primitive rangeKey)
{
AddKeyToDelete(TargetTable.MakeKey(hashKey, rangeKey));
}
- ///
- /// Add a single item to delete, identified by its key.
- ///
- /// Key of the item to delete.
+ ///
public void AddKeyToDelete(IDictionary key)
{
AddKeyToDelete(TargetTable.MakeKey(key));
}
- ///
- /// Add a single item to delete, identified by a Document object.
- ///
- /// Document representing the item to be deleted.
+ ///
public void AddItemToDelete(Document document)
{
AddKeyToDelete(TargetTable.MakeKey(document));
@@ -100,10 +134,7 @@ public void AddItemToDelete(Document document)
#region Public Put methods
- ///
- /// Add a single Document to put.
- ///
- /// Document to put.
+ ///
public void AddDocumentToPut(Document document)
{
ToPut.Add(document);
@@ -114,16 +145,8 @@ public void AddDocumentToPut(Document document)
#region Public methods
- ///
- /// Creates a MultiTableDocumentBatchWrite object that is a combination
- /// of the current DocumentBatchWrite and the specified DocumentBatchWrite.
- ///
- /// Other DocumentBatchWrite object.
- ///
- /// MultiTableDocumentBatchWrite consisting of the two DocumentBatchWrite
- /// objects.
- ///
- public MultiTableDocumentBatchWrite Combine(DocumentBatchWrite otherBatch)
+ ///
+ public MultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch)
{
return new MultiTableDocumentBatchWrite(this, otherBatch);
}
@@ -162,17 +185,32 @@ internal void AddKeyToDelete(Key key)
}
///
- /// Class for putting and/or deleting a batch of items in multiple DynamoDB tables.
+ /// Interface for putting and/or deleting a batch of items in multiple DynamoDB tables.
///
- public partial class MultiTableDocumentBatchWrite
+ public partial interface IMultiTableDocumentBatchWrite
{
- #region Properties
-
///
/// List of DocumentBatchWrite objects to include in the multi-table
/// batch request.
///
- public List Batches { get; private set; }
+ List Batches { get; }
+
+ ///
+ /// Add a DocumentBatchWrite object to the multi-table batch request.
+ ///
+ /// DocumentBatchWrite to add.
+ void AddBatch(IDocumentBatchWrite batch);
+ }
+
+ ///
+ /// Class for putting and/or deleting a batch of items in multiple DynamoDB tables.
+ ///
+ public partial class MultiTableDocumentBatchWrite : IMultiTableDocumentBatchWrite
+ {
+ #region Properties
+
+ ///
+ public List Batches { get; private set; }
#endregion
@@ -184,12 +222,12 @@ public partial class MultiTableDocumentBatchWrite
/// DocumentBatchWrite objects.
///
/// Collection of DocumentBatchWrite objects.
- public MultiTableDocumentBatchWrite(params DocumentBatchWrite[] batches)
+ public MultiTableDocumentBatchWrite(params IDocumentBatchWrite[] batches)
{
if (batches == null)
throw new ArgumentNullException("batches");
- Batches = new List(batches);
+ Batches = new List(batches);
}
#endregion
@@ -197,11 +235,8 @@ public MultiTableDocumentBatchWrite(params DocumentBatchWrite[] batches)
#region Public methods
- ///
- /// Add a DocumentBatchWrite object to the multi-table batch request.
- ///
- /// DocumentBatchWrite to add.
- public void AddBatch(DocumentBatchWrite batch)
+ ///
+ public void AddBatch(IDocumentBatchWrite batch)
{
Batches.Add(batch);
}
@@ -213,9 +248,10 @@ public void AddBatch(DocumentBatchWrite batch)
internal void ExecuteHelper()
{
+ var errMsg = $"All {nameof(IDocumentBatchWrite)} objects must be of type {nameof(DocumentBatchWrite)}";
MultiBatchWrite multiBatchWrite = new MultiBatchWrite
{
- Batches = Batches
+ Batches = Batches.Select(x => x as DocumentBatchWrite ?? throw new InvalidOperationException(errMsg)).ToList()
};
multiBatchWrite.WriteItems();
}
@@ -223,9 +259,10 @@ internal void ExecuteHelper()
#if AWS_ASYNC_API
internal Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
+ var errMsg = $"All {nameof(IDocumentBatchWrite)} objects must be of type {nameof(DocumentBatchWrite)}";
MultiBatchWrite multiBatchWrite = new MultiBatchWrite
{
- Batches = Batches
+ Batches = Batches.Select(x => x as DocumentBatchWrite ?? throw new InvalidOperationException(errMsg)).ToList()
};
return multiBatchWrite.WriteItemsAsync(cancellationToken);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index 5316f29ab66a..6a7ad2cabd0d 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -1575,7 +1575,7 @@ public IDocumentBatchGet CreateBatchGet()
/// a batch-put/delete operation against DynamoDB.
///
/// Empty DocumentBatchWrite object.
- public DocumentBatchWrite CreateBatchWrite()
+ public IDocumentBatchWrite CreateBatchWrite()
{
return new DocumentBatchWrite(this);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
index 2a01e95897fa..208849876f9b 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
@@ -14,25 +14,13 @@
*/
#pragma warning disable 1574
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-using Amazon.Runtime.Internal;
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for putting and/or deleting a batch of items in a single DynamoDB table.
- ///
- public partial class DocumentBatchWrite
+ public partial interface IDocumentBatchWrite
{
- #region Public methods
-
///
/// Executes a server call to batch-put/delete the item specified.
///
@@ -41,21 +29,20 @@ public partial class DocumentBatchWrite
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class DocumentBatchWrite : IDocumentBatchWrite
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
- ///
- /// Class for putting and/or deleting a batch of items in multiple DynamoDB tables.
- ///
- public partial class MultiTableDocumentBatchWrite
+ public partial interface IMultiTableDocumentBatchWrite
{
- #region Public methods
-
///
/// Executes a multi-table batch put/delete against all configured batches.
///
@@ -64,11 +51,15 @@ public partial class MultiTableDocumentBatchWrite
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class MultiTableDocumentBatchWrite
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchWrite.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchWrite.Sync.cs
index d079765f6870..826e73d584b4 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchWrite.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchWrite.Sync.cs
@@ -13,54 +13,45 @@
* permissions and limitations under the License.
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for putting and/or deleting a batch of items in a single DynamoDB table.
- ///
- public partial class DocumentBatchWrite
+ public partial interface IDocumentBatchWrite
{
- #region Public methods
-
///
/// Executes a server call to batch-put/delete the item specified.
///
/// If more than 25 put/delete operations are specified, calls of up to 25
/// put/delete items will be made until all items are processed.
///
+ void Execute();
+ }
+
+ public partial class DocumentBatchWrite : IDocumentBatchWrite
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
- ///
- /// Class for putting and/or deleting a batch of items in multiple DynamoDB tables.
- ///
- public partial class MultiTableDocumentBatchWrite
+ public partial interface IMultiTableDocumentBatchWrite
{
- #region Public methods
-
///
/// Executes a multi-table batch put/delete against all configured batches.
- ///
+ ///
/// If more than 25 put/delete operations are specified, calls of up to 25
/// put/delete items will be made until all items are processed.
///
+ void Execute();
+ }
+
+ public partial class MultiTableDocumentBatchWrite : IMultiTableDocumentBatchWrite
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
}
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs
new file mode 100644
index 000000000000..37aa085cf177
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs
@@ -0,0 +1,114 @@
+using Amazon.DynamoDBv2.DocumentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class DocumentBatchWriteTests
+ {
+ [TestMethod]
+ public void TestMockability_DocumentBatchWrite()
+ {
+ var itemsToPut = new List();
+ var inMemoryTable = new List();
+
+ var batchWrite = CreateDocumentBatchWriteMock(itemsToPut, inMemoryTable);
+
+ Assert.AreEqual(0, inMemoryTable.Count);
+ Assert.AreEqual(0, itemsToPut.Count);
+
+ batchWrite.AddDocumentToPut(new Document { { "key1", "value1" } });
+ batchWrite.AddDocumentToPut(new Document { { "key2", "value2" } });
+ Assert.AreEqual(2, itemsToPut.Count);
+ Assert.AreEqual(0, inMemoryTable.Count);
+
+ batchWrite.Execute();
+ Assert.AreEqual(0, itemsToPut.Count);
+ Assert.AreEqual(2, inMemoryTable.Count);
+
+ var firstDoc = inMemoryTable.First();
+ Assert.AreEqual("value1", firstDoc["key1"].AsString());
+
+ var secondDoc = inMemoryTable.Skip(1).First();
+ Assert.AreEqual("value2", secondDoc["key2"].AsString());
+ }
+
+ [TestMethod]
+ public void TestMockability_MultiTableDocumentBatchWrite()
+ {
+ var itemsToPut_table1 = new List();
+ var inMemory_table1 = new List();
+ var batchWrite_table1 = CreateDocumentBatchWriteMock(itemsToPut_table1, inMemory_table1);
+ batchWrite_table1.AddDocumentToPut(new Document { { "key1", "value1" } });
+
+ var itemsToPut_table2 = new List();
+ var inMemory_table2 = new List();
+ var batchWrite_table2 = CreateDocumentBatchWriteMock(itemsToPut_table2, inMemory_table2);
+ batchWrite_table2.AddDocumentToPut(new Document { { "key2", "value2" } });
+
+ var multiBatchWrite = CreateMultiTableDocumentBatchWriteMock();
+ multiBatchWrite.AddBatch(batchWrite_table1);
+ multiBatchWrite.AddBatch(batchWrite_table2);
+
+ Assert.AreEqual(0, inMemory_table1.Count);
+ Assert.AreEqual(0, inMemory_table2.Count);
+
+ multiBatchWrite.Execute();
+ Assert.AreEqual(1, inMemory_table1.Count);
+ Assert.AreEqual(1, inMemory_table2.Count);
+ Assert.AreEqual("value1", inMemory_table1.First()["key1"].AsString());
+ Assert.AreEqual("value2", inMemory_table2.First()["key2"].AsString());
+ }
+
+ public IDocumentBatchWrite CreateDocumentBatchWriteMock(List itemsToPut, List inMemoryTable)
+ {
+ var batchWrite = new Mock();
+
+ batchWrite
+ .Setup(x => x.AddDocumentToPut(It.IsAny()))
+ .Callback((Document item) => itemsToPut.Add(item));
+
+ batchWrite.
+ Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var item in itemsToPut)
+ {
+ inMemoryTable.Add(item);
+ }
+
+ itemsToPut.Clear();
+ });
+
+ return batchWrite.Object;
+ }
+
+ public IMultiTableDocumentBatchWrite CreateMultiTableDocumentBatchWriteMock()
+ {
+ var multiBatchWrite = new Mock();
+ var batches = new List();
+
+ multiBatchWrite
+ .Setup(x => x.AddBatch(It.IsAny()))
+ .Callback((IDocumentBatchWrite batch) =>
+ {
+ batches.Add(batch);
+ });
+
+ multiBatchWrite
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var batch in batches)
+ {
+ batch.Execute();
+ }
+ });
+
+ return multiBatchWrite.Object;
+ }
+ }
+}
From 8d88f4fe1b2238e9bc89ecf75ea5d9afbf527f22 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Thu, 15 Aug 2024 13:02:09 -0700
Subject: [PATCH 3/7] Add the ability to mock DocumentTransactGet and
MultiTableDocumentTransactGet operations
---
.../Custom/DataModel/TransactGet.cs | 5 +-
.../DocumentModel/DocumentTransactGet.cs | 195 +++++++++++-------
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 2 +-
.../_async/DocumentBatchWrite.Async.cs | 2 +-
.../_async/DocumentTransactGet.Async.cs | 30 +--
.../_bcl/DocumentBatchGet.Sync.cs | 2 +-
.../_bcl/DocumentTransactGet.Sync.cs | 30 ++-
.../DocumentTransactGetTests.cs | 118 +++++++++++
8 files changed, 278 insertions(+), 106 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs
index a2907383a896..7daa14368bb6 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs
@@ -157,7 +157,10 @@ internal TransactGet(DynamoDBContext context, DynamoDBFlatConfig config)
_config = config;
_storageConfig = context.StorageConfigCache.GetConfig(config);
var table = context.GetTargetTable(_storageConfig, config);
- DocumentTransaction = table.CreateTransactGet();
+
+ // Table.CreateTransactGet() returns the IDocumentTransactGet interface.
+ // But since we rely on the internal behavior of DocumentTransactGet, we instantiate it via the constructor.
+ DocumentTransaction = new DocumentTransactGet(table);
}
private void ExecuteHelper()
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
index 354b87c14a98..75057a6b9e89 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
@@ -27,7 +27,82 @@ namespace Amazon.DynamoDBv2.DocumentModel
///
/// Class for retrieving multiple Documents from a single DynamoDB table in a transaction.
///
- public partial class DocumentTransactGet
+ public partial interface IDocumentTransactGet
+ {
+ ///
+ /// List of results retrieved from DynamoDB.
+ /// Populated after Execute is called.
+ ///
+ List Results { get; }
+
+ ///
+ /// Add a single item to get, identified by its hash primary key,
+ /// using the specified expression to identify the attributes to retrieve.
+ ///
+ /// Hash key element of the item to get.
+ ///
+ /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
+ ///
+ void AddKey(Primitive hashKey, Expression projectionExpression);
+
+ ///
+ /// Add a single item to get, identified by its hash primary key, using the specified config.
+ ///
+ /// Hash key element of the item to get.
+ /// Configuration to use.
+ void AddKey(Primitive hashKey, TransactGetItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to get, identified by its hash-and-range primary key,
+ /// using the specified expression to identify the attributes to retrieve.
+ ///
+ /// Hash key element of the item to get.
+ /// Range key element of the item to get.
+ ///
+ /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
+ ///
+ void AddKey(Primitive hashKey, Primitive rangeKey, Expression projectionExpression);
+
+ ///
+ /// Add a single item to get, identified by its hash-and-range primary key, using the specified config.
+ ///
+ /// Hash key element of the item to get.
+ /// Range key element of the item to get.
+ /// Configuration to use.
+ void AddKey(Primitive hashKey, Primitive rangeKey, TransactGetItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to get, identified by its key,
+ /// using the specified expression to identify the attributes to retrieve.
+ ///
+ /// Key of the item to get.
+ ///
+ /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
+ ///
+ void AddKey(IDictionary key, Expression projectionExpression);
+
+ ///
+ /// Add a single item to get, identified by its key, using the specified config.
+ ///
+ /// Key of the item to get.
+ /// Configuration to use.
+ void AddKey(IDictionary key, TransactGetItemOperationConfig operationConfig = null);
+
+ ///
+ /// Creates a MultiTableDocumentTransactGet object that is a combination
+ /// of the current DocumentTransactGet and the specified DocumentTransactGet.
+ ///
+ /// Other DocumentTransactGet object.
+ ///
+ /// MultiTableDocumentTransactGet consisting of the two DocumentTransactGet objects.
+ ///
+ MultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart);
+ }
+
+ ///
+ /// Class for retrieving multiple Documents from a single DynamoDB table in a transaction.
+ ///
+ public partial class DocumentTransactGet : IDocumentTransactGet
{
#region Internal properties
@@ -39,10 +114,7 @@ public partial class DocumentTransactGet
#region Public properties
- ///
- /// List of results retrieved from DynamoDB.
- /// Populated after Execute is called.
- ///
+ ///
public List Results { get; internal set; }
#endregion
@@ -65,86 +137,44 @@ public DocumentTransactGet(Table targetTable)
#region Public methods
- ///
- /// Add a single item to get, identified by its hash primary key,
- /// using the specified expression to identify the attributes to retrieve.
- ///
- /// Hash key element of the item to get.
- ///
- /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
- ///
+ ///
public void AddKey(Primitive hashKey, Expression projectionExpression)
{
AddKey(hashKey, new TransactGetItemOperationConfig { ProjectionExpression = projectionExpression });
}
- ///
- /// Add a single item to get, identified by its hash primary key, using the specified config.
- ///
- /// Hash key element of the item to get.
- /// Configuration to use.
+ ///
public void AddKey(Primitive hashKey, TransactGetItemOperationConfig operationConfig = null)
{
AddKey(hashKey, rangeKey: null, operationConfig);
}
- ///
- /// Add a single item to get, identified by its hash-and-range primary key,
- /// using the specified expression to identify the attributes to retrieve.
- ///
- /// Hash key element of the item to get.
- /// Range key element of the item to get.
- ///
- /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
- ///
+ ///
public void AddKey(Primitive hashKey, Primitive rangeKey, Expression projectionExpression)
{
AddKey(hashKey, rangeKey, new TransactGetItemOperationConfig { ProjectionExpression = projectionExpression });
}
- ///
- /// Add a single item to get, identified by its hash-and-range primary key, using the specified config.
- ///
- /// Hash key element of the item to get.
- /// Range key element of the item to get.
- /// Configuration to use.
+ ///
public void AddKey(Primitive hashKey, Primitive rangeKey, TransactGetItemOperationConfig operationConfig = null)
{
AddKeyHelper(TargetTable.MakeKey(hashKey, rangeKey), operationConfig);
}
- ///
- /// Add a single item to get, identified by its key,
- /// using the specified expression to identify the attributes to retrieve.
- ///
- /// Key of the item to get.
- ///
- /// An expression that identifies one or more attributes of the specified item to retrieve from the table.
- ///
+ ///
public void AddKey(IDictionary key, Expression projectionExpression)
{
AddKey(key, new TransactGetItemOperationConfig { ProjectionExpression = projectionExpression });
}
- ///
- /// Add a single item to get, identified by its key, using the specified config.
- ///
- /// Key of the item to get.
- /// Configuration to use.
+ ///
public void AddKey(IDictionary key, TransactGetItemOperationConfig operationConfig = null)
{
AddKeyHelper(TargetTable.MakeKey(key), operationConfig);
}
- ///
- /// Creates a MultiTableDocumentTransactGet object that is a combination
- /// of the current DocumentTransactGet and the specified DocumentTransactGet.
- ///
- /// Other DocumentTransactGet object.
- ///
- /// MultiTableDocumentTransactGet consisting of the two DocumentTransactGet objects.
- ///
- public MultiTableDocumentTransactGet Combine(DocumentTransactGet otherTransactionPart)
+ ///
+ public MultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart)
{
return new MultiTableDocumentTransactGet(this, otherTransactionPart);
}
@@ -190,17 +220,32 @@ private MultiTransactGet GetMultiTransactGet()
}
///
- /// Class for retrieving multiple Documents from multiple DynamoDB tables in a transaction.
+ /// Interface for retrieving multiple Documents from multiple DynamoDB tables in a transaction.
///
- public partial class MultiTableDocumentTransactGet
+ public partial interface IMultiTableDocumentTransactGet
{
- #region Properties
-
///
/// List of DocumentTransactGet objects to include in the multi-table
/// transaction request.
///
- public List TransactionParts { get; private set; }
+ List TransactionParts { get; }
+
+ ///
+ /// Add a DocumentTransactGet object to the multi-table transaction request.
+ ///
+ /// DocumentTransactGet to add.
+ void AddTransactionPart(IDocumentTransactGet transactionPart);
+ }
+
+ ///
+ /// Class for retrieving multiple Documents from multiple DynamoDB tables in a transaction.
+ ///
+ public partial class MultiTableDocumentTransactGet : IMultiTableDocumentTransactGet
+ {
+ #region Properties
+
+ ///
+ public List TransactionParts { get; private set; }
#endregion
@@ -212,12 +257,12 @@ public partial class MultiTableDocumentTransactGet
/// DocumentTransactGet objects.
///
/// Collection of DocumentTransactGet objects.
- public MultiTableDocumentTransactGet(params DocumentTransactGet[] transactionParts)
+ public MultiTableDocumentTransactGet(params IDocumentTransactGet[] transactionParts)
{
if (transactionParts == null)
throw new ArgumentNullException(nameof(transactionParts));
- TransactionParts = new List(transactionParts);
+ TransactionParts = new List(transactionParts);
}
#endregion
@@ -225,11 +270,8 @@ public MultiTableDocumentTransactGet(params DocumentTransactGet[] transactionPar
#region Public methods
- ///
- /// Add a DocumentTransactGet object to the multi-table transaction request.
- ///
- /// DocumentTransactGet to add.
- public void AddTransactionPart(DocumentTransactGet transactionPart)
+ ///
+ public void AddTransactionPart(IDocumentTransactGet transactionPart)
{
TransactionParts.Add(transactionPart);
}
@@ -242,11 +284,13 @@ public void AddTransactionPart(DocumentTransactGet transactionPart)
internal void ExecuteHelper()
{
var items = GetMultiTransactGet().GetItems();
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactGet)}";
foreach (var transactionPart in TransactionParts)
{
- items.TryGetValue(transactionPart, out var results);
- transactionPart.Results = results ?? new List();
+ var docTransactGet = transactionPart as DocumentTransactGet ?? throw new InvalidOperationException(errMsg);
+ items.TryGetValue(docTransactGet, out var results);
+ docTransactGet.Results = results ?? new List();
}
}
@@ -254,20 +298,27 @@ internal void ExecuteHelper()
internal async Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
var items = await GetMultiTransactGet().GetItemsAsync(cancellationToken).ConfigureAwait(false);
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactGet)}";
foreach (var transactionPart in TransactionParts)
{
- items.TryGetValue(transactionPart, out var results);
- transactionPart.Results = results ?? new List();
+ var docTransactGet = transactionPart as DocumentTransactGet ?? throw new InvalidOperationException(errMsg);
+ items.TryGetValue(docTransactGet, out var results);
+ docTransactGet.Results = results ?? new List();
}
}
#endif
private MultiTransactGet GetMultiTransactGet()
{
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactGet)}";
return new MultiTransactGet
{
- Items = TransactionParts.SelectMany(x => x.Items).ToList()
+ Items = TransactionParts.SelectMany(x =>
+ {
+ var docTransactGet = x as DocumentTransactGet ?? throw new InvalidOperationException(errMsg);
+ return docTransactGet.Items;
+ }).ToList()
};
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index 6a7ad2cabd0d..1ac032d690ea 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -1590,7 +1590,7 @@ public IDocumentBatchWrite CreateBatchWrite()
/// a transactional get operation against DynamoDB.
///
/// Empty DocumentTransactGet object.
- public DocumentTransactGet CreateTransactGet()
+ public IDocumentTransactGet CreateTransactGet()
{
return new DocumentTransactGet(this);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
index 208849876f9b..aa791aceb1e8 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs
@@ -54,7 +54,7 @@ public partial interface IMultiTableDocumentBatchWrite
Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
}
- public partial class MultiTableDocumentBatchWrite
+ public partial class MultiTableDocumentBatchWrite : IMultiTableDocumentBatchWrite
{
///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactGet.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactGet.Async.cs
index edaabedc1c5f..3a3a3239c3ca 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactGet.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactGet.Async.cs
@@ -18,10 +18,7 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for retrieving multiple Documents from a single DynamoDB table in a transaction.
- ///
- public partial class DocumentTransactGet
+ public partial interface IDocumentTransactGet
{
#region Public methods
@@ -31,32 +28,37 @@ public partial class DocumentTransactGet
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+
+ #endregion
+ }
+
+ public partial class DocumentTransactGet : IDocumentTransactGet
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
- ///
- /// Class for retrieving multiple Documents from multiple DynamoDB tables in a transaction.
- ///
- public partial class MultiTableDocumentTransactGet
+ public partial interface IMultiTableDocumentTransactGet
{
- #region Public methods
-
///
/// Executes a multi-table transaction request against all configured DocumentTransactGet objects.
/// Results are stored in the respective DocumentTransactGet objects.
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class MultiTableDocumentTransactGet : IMultiTableDocumentTransactGet
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
index 1b68f7ab14bc..f43592e50f76 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentBatchGet.Sync.cs
@@ -42,7 +42,7 @@ public partial interface IMultiTableDocumentBatchGet
void Execute();
}
- public partial class MultiTableDocumentBatchGet
+ public partial class MultiTableDocumentBatchGet : IMultiTableDocumentBatchGet
{
///
public void Execute()
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactGet.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactGet.Sync.cs
index ded4b339ac27..2827a4660611 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactGet.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactGet.Sync.cs
@@ -15,41 +15,39 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for retrieving multiple Documents from a single DynamoDB table in a transaction.
- ///
- public partial class DocumentTransactGet
+ public partial interface IDocumentTransactGet
{
- #region Public methods
-
///
/// Executes a server call to get the documents requested in a transaction.
/// Populates Results with the retrieved items.
///
+ void Execute();
+ }
+
+ public partial class DocumentTransactGet : IDocumentTransactGet
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
- ///
- /// Class for retrieving multiple Documents from multiple DynamoDB tables in a transaction.
- ///
- public partial class MultiTableDocumentTransactGet
+ public partial interface IMultiTableDocumentTransactGet
{
- #region Public methods
-
///
/// Executes a multi-table transaction request against all configured DocumentTransactGet objects.
/// Results are stored in the respective DocumentTransactGet objects.
///
+ void Execute();
+ }
+
+ public partial class MultiTableDocumentTransactGet : IMultiTableDocumentTransactGet
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
}
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs
new file mode 100644
index 000000000000..20ca16a5b453
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs
@@ -0,0 +1,118 @@
+using Amazon.DynamoDBv2.DocumentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class DocumentTransactGetTests
+ {
+ [TestMethod]
+ public void TestMockability_DocumentTransactGet()
+ {
+ var dummyResults = new List()
+ {
+ new Document()
+ {
+ {"State", "CA"},
+ {"Zip", "12345"}
+ }
+ };
+
+ var addressTransactGet = CreateDocumentTransactGetMock(dummyResults);
+
+ Assert.AreEqual(0, addressTransactGet.Results.Count);
+
+ addressTransactGet.Execute();
+ Assert.AreEqual(1, addressTransactGet.Results.Count);
+ Assert.AreEqual("CA", addressTransactGet.Results[0]["State"].AsString());
+ Assert.AreEqual("12345", addressTransactGet.Results[0]["Zip"].AsString());
+ }
+
+ [TestMethod]
+ public void TestMockability_MultiTableDocumentTransactGet()
+ {
+ var addressTransactGet = CreateDocumentTransactGetMock(new List
+ {
+ new Document()
+ {
+ {"State", "CA"},
+ {"Zip", "12345"}
+ }
+ });
+
+ var personTransactGet = CreateDocumentTransactGetMock(new List
+ {
+ new Document()
+ {
+ {"FirstName", "John"},
+ {"LastName", "Doe"}
+ }
+ });
+
+ var multiTransactGet = CreateMultiTableDocumentTransactGetMock();
+ multiTransactGet.AddTransactionPart(addressTransactGet);
+ multiTransactGet.AddTransactionPart(personTransactGet);
+
+ Assert.AreEqual(0, addressTransactGet.Results.Count);
+ Assert.AreEqual(0, personTransactGet.Results.Count);
+
+ multiTransactGet.Execute();
+
+ Assert.AreEqual(1, addressTransactGet.Results.Count);
+ Assert.AreEqual("CA", addressTransactGet.Results[0]["State"].AsString());
+ Assert.AreEqual("12345", addressTransactGet.Results[0]["Zip"].AsString());
+
+ Assert.AreEqual(1, personTransactGet.Results.Count);
+ Assert.AreEqual("John", personTransactGet.Results[0]["FirstName"].AsString());
+ Assert.AreEqual("Doe", personTransactGet.Results[0]["LastName"].AsString());
+ }
+
+ public IDocumentTransactGet CreateDocumentTransactGetMock(List results)
+ {
+ var transactGet = new Mock();
+ var dummyResults = new List();
+ var keys = new List();
+
+ transactGet
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ dummyResults.Clear();
+ dummyResults.AddRange(results);
+ });
+
+ transactGet
+ .Setup(x => x.Results)
+ .Returns(dummyResults);
+
+ return transactGet.Object;
+ }
+
+ public IMultiTableDocumentTransactGet CreateMultiTableDocumentTransactGetMock()
+ {
+ var multiTransactGet = new Mock();
+ var batches = new List();
+
+ multiTransactGet
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var batch in batches)
+ {
+ batch.Execute();
+ }
+ });
+
+ multiTransactGet
+ .Setup(x => x.AddTransactionPart(It.IsAny()))
+ .Callback((IDocumentTransactGet batch) =>
+ {
+ batches.Add(batch);
+ });
+
+ return multiTransactGet.Object;
+ }
+ }
+}
From 004e58ad66df6f88853061e12e6faf081d72bbc3 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Thu, 15 Aug 2024 15:48:53 -0700
Subject: [PATCH 4/7] Add the ability to mock DocumentTransactWrite and
MultiTableDocumentTransactWrite operations
---
.../Custom/DataModel/TransactWrite.cs | 5 +-
.../DocumentModel/DocumentTransactWrite.cs | 386 +++++++++++-------
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 2 +-
.../_async/DocumentTransactWrite.Async.cs | 32 +-
.../_bcl/DocumentTransactWrite.Sync.cs | 32 +-
.../DocumentTransactWriteTests.cs | 113 +++++
6 files changed, 388 insertions(+), 182 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.cs
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs
index 42ff4668e246..de61ba6addaa 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs
@@ -188,7 +188,10 @@ internal TransactWrite(DynamoDBContext context, DynamoDBFlatConfig config)
_config = config;
_storageConfig = context.StorageConfigCache.GetConfig(config);
Table table = _context.GetTargetTable(_storageConfig, _config);
- DocumentTransaction = table.CreateTransactWrite();
+
+ // table.CreateTransactWrite() return the IDocumentTransactWrite interface.
+ // But since we rely on the internal behavior of DocumentTransactWrite, we instatiate it via the constructor.
+ DocumentTransaction = new DocumentTransactWrite(table);
}
///
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
index cff407032037..da0a29f542ab 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
@@ -24,6 +24,182 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
+ ///
+ /// Interface for condition checking, putting, updating and/or deleting
+ /// multiple items in a single DynamoDB table in a transaction.
+ ///
+ public partial interface IDocumentTransactWrite
+ {
+ ///
+ /// List of items retrieved from DynamoDB for which a condition check failure happened.
+ /// Populated after Execute is called and a TransactionCanceledException happened due to a condition check failure.
+ /// A document is only added to this list if ReturnValuesOnConditionCheckFailure has been set to AllOldAttributes
+ /// for the corresponding item in the request.
+ ///
+ List ConditionCheckFailedItems { get; }
+
+ ///
+ /// Add a single item to delete, identified by its hash primary key, using the specified config.
+ ///
+ /// Hash key element of the item to delete.
+ /// Configuration to use.
+ void AddKeyToDelete(Primitive hashKey, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to delete, identified by its hash-and-range primary key, using the specified config.
+ ///
+ /// Hash key element of the item to delete.
+ /// Range key element of the item to delete.
+ /// Configuration to use.
+ void AddKeyToDelete(Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to delete, identified by its key, using the specified config.
+ ///
+ /// Key of the item to delete.
+ /// Configuration to use.
+ void AddKeyToDelete(IDictionary key, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to delete, identified by a Document object, using the specified config.
+ ///
+ /// Document representing the item to be deleted.
+ /// Configuration to use.
+ void AddItemToDelete(Document document, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single Document to update, identified by its hash primary key, using the specified config.
+ ///
+ /// Attributes to update.
+ /// Hash key of the document.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Document document, Primitive hashKey, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single Document to update, identified by its hash-and-range primary key, using the specified config.
+ ///
+ /// Attributes to update.
+ /// Hash key of the document.
+ /// Range key of the document.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Document document, Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single Document to update, identified by its key, using the specified config.
+ ///
+ /// Attributes to update.
+ /// Key of the document.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Document document, IDictionary key, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single Document to update, using the specified config.
+ ///
+ /// Document to update.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Document document, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to update, identified by its hash primary key, using the specified update expression and config.
+ ///
+ /// Hash key of the document.
+ /// Update expression to use.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Primitive hashKey, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to update, identified by its hash-and-range primary key, using the specified update expression and config.
+ ///
+ /// Hash key of the document.
+ /// Range key of the document.
+ /// Update expression to use.
+ /// Configuration to use.
+ void AddDocumentToUpdate(Primitive hashKey, Primitive rangeKey, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to update, identified by its key, using the specified update expression and config.
+ ///
+ /// Key of the document.
+ /// Update expression to use.
+ /// Configuration to use.
+ void AddDocumentToUpdate(IDictionary key, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single Document to put, using the specified config.
+ ///
+ /// Document to put.
+ /// Configuration to use.
+ void AddDocumentToPut(Document document, TransactWriteItemOperationConfig operationConfig = null);
+
+ ///
+ /// Add a single item to condition check, identified by its hash primary key, using the specified condition expression.
+ ///
+ /// Hash key of the item.
+ /// The expression to evaluate for the item.
+ void AddKeyToConditionCheck(Primitive hashKey, Expression conditionalExpression);
+
+ ///
+ /// Add a single item to condition check, identified by its hash primary key, using the specified config.
+ ///
+ /// Hash key of the item.
+ /// Configuration to use.
+ void AddKeyToConditionCheck(Primitive hashKey, TransactWriteItemOperationConfig operationConfig);
+
+ ///
+ /// Add a single item to condition check, identified by its hash-and-range primary key, using the specified condition expression.
+ ///
+ /// Hash key of the item.
+ /// Range key of the item.
+ /// The expression to evaluate for the item.
+ void AddKeyToConditionCheck(Primitive hashKey, Primitive rangeKey, Expression conditionalExpression);
+
+ ///
+ /// Add a single item to condition check, identified by its hash-and-range primary key, using the specified config.
+ ///
+ /// Hash key of the item.
+ /// Range key of the item.
+ /// Configuration to use.
+ void AddKeyToConditionCheck(Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig);
+
+ ///
+ /// Add a single item to condition check, identified by its key, using the specified condition expression.
+ ///
+ /// Key of the item.
+ /// The expression to evaluate for the item.
+ void AddKeyToConditionCheck(IDictionary key, Expression conditionalExpression);
+
+ ///
+ /// Add a single item to condition check, identified by its key, using the specified config.
+ ///
+ /// Key of the item.
+ /// Configuration to use.
+ void AddKeyToConditionCheck(IDictionary key, TransactWriteItemOperationConfig operationConfig);
+
+ ///
+ /// Add a single item to condition check, identified by a Document object, using the specified condition expression.
+ ///
+ /// Document representing the item.
+ /// The expression to evaluate for the item.
+ void AddItemToConditionCheck(Document document, Expression conditionalExpression);
+
+ ///
+ /// Add a single item to condition check, identified by a Document object, using the specified config.
+ ///
+ /// Document representing the item.
+ /// Configuration to use.
+ void AddItemToConditionCheck(Document document, TransactWriteItemOperationConfig operationConfig);
+
+ ///
+ /// Creates a MultiTableDocumentTransactWrite object that is a combination
+ /// of the current DocumentTransactWrite and the specified DocumentTransactWrite.
+ ///
+ /// Other DocumentTransactWrite object.
+ ///
+ /// MultiTableDocumentTransactWrite consisting of the two DocumentTransactWrite objects.
+ ///
+ MultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart);
+ }
+
///
/// Class for condition checking, putting, updating and/or deleting
/// multiple items in a single DynamoDB table in a transaction.
@@ -31,7 +207,7 @@ namespace Amazon.DynamoDBv2.DocumentModel
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
#endif
- public partial class DocumentTransactWrite
+ public partial class DocumentTransactWrite : IDocumentTransactWrite
{
#region Internal properties
@@ -43,12 +219,7 @@ public partial class DocumentTransactWrite
#region Public properties
- ///
- /// List of items retrieved from DynamoDB for which a condition check failure happened.
- /// Populated after Execute is called and a TransactionCanceledException happened due to a condition check failure.
- /// A document is only added to this list if ReturnValuesOnConditionCheckFailure has been set to AllOldAttributes
- /// for the corresponding item in the request.
- ///
+ ///
public List ConditionCheckFailedItems { get; internal set; }
#endregion
@@ -56,10 +227,7 @@ public partial class DocumentTransactWrite
#region Constructor
- ///
- /// Constructs a DocumentTransactWrite instance for a specific table.
- ///
- /// Table to get items from.
+ ///
public DocumentTransactWrite(Table targetTable)
{
TargetTable = targetTable;
@@ -71,42 +239,25 @@ public DocumentTransactWrite(Table targetTable)
#region Public Delete methods
- ///
- /// Add a single item to delete, identified by its hash primary key, using the specified config.
- ///
- /// Hash key element of the item to delete.
- /// Configuration to use.
+ ///
public void AddKeyToDelete(Primitive hashKey, TransactWriteItemOperationConfig operationConfig = null)
{
AddKeyToDelete(hashKey, rangeKey: null, operationConfig);
}
- ///
- /// Add a single item to delete, identified by its hash-and-range primary key, using the specified config.
- ///
- /// Hash key element of the item to delete.
- /// Range key element of the item to delete.
- /// Configuration to use.
+ ///
public void AddKeyToDelete(Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig = null)
{
AddKeyToDeleteHelper(TargetTable.MakeKey(hashKey, rangeKey), operationConfig);
}
- ///
- /// Add a single item to delete, identified by its key, using the specified config.
- ///
- /// Key of the item to delete.
- /// Configuration to use.
+ ///
public void AddKeyToDelete(IDictionary key, TransactWriteItemOperationConfig operationConfig = null)
{
AddKeyToDeleteHelper(TargetTable.MakeKey(key), operationConfig);
}
- ///
- /// Add a single item to delete, identified by a Document object, using the specified config.
- ///
- /// Document representing the item to be deleted.
- /// Configuration to use.
+ ///
public void AddItemToDelete(Document document, TransactWriteItemOperationConfig operationConfig = null)
{
AddKeyToDeleteHelper(TargetTable.MakeKey(document), operationConfig);
@@ -117,79 +268,43 @@ public void AddItemToDelete(Document document, TransactWriteItemOperationConfig
#region Public Update methods
- ///
- /// Add a single Document to update, identified by its hash primary key, using the specified config.
- ///
- /// Attributes to update.
- /// Hash key of the document.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Document document, Primitive hashKey, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdate(document, hashKey, rangeKey: null, operationConfig);
}
- ///
- /// Add a single Document to update, identified by its hash-and-range primary key, using the specified config.
- ///
- /// Attributes to update.
- /// Hash key of the document.
- /// Range key of the document.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Document document, Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdateHelper(document, TargetTable.MakeKey(hashKey, rangeKey), operationConfig);
}
- ///
- /// Add a single Document to update, identified by its key, using the specified config.
- ///
- /// Attributes to update.
- /// Key of the document.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Document document, IDictionary key, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdateHelper(document, TargetTable.MakeKey(key), operationConfig);
}
- ///
- /// Add a single Document to update, using the specified config.
- ///
- /// Document to update.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Document document, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdateHelper(document, TargetTable.MakeKey(document), operationConfig);
}
- ///
- /// Add a single item to update, identified by its hash primary key, using the specified update expression and config.
- ///
- /// Hash key of the document.
- /// Update expression to use.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Primitive hashKey, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdate(hashKey, rangeKey: null, updateExpression, operationConfig);
}
- ///
- /// Add a single item to update, identified by its hash-and-range primary key, using the specified update expression and config.
- ///
- /// Hash key of the document.
- /// Range key of the document.
- /// Update expression to use.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(Primitive hashKey, Primitive rangeKey, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdateHelper(TargetTable.MakeKey(hashKey, rangeKey), updateExpression, operationConfig);
}
- ///
- /// Add a single item to update, identified by its key, using the specified update expression and config.
- ///
- /// Key of the document.
- /// Update expression to use.
- /// Configuration to use.
+ ///
public void AddDocumentToUpdate(IDictionary key, Expression updateExpression, TransactWriteItemOperationConfig operationConfig = null)
{
AddDocumentToUpdateHelper(TargetTable.MakeKey(key), updateExpression, operationConfig);
@@ -200,11 +315,7 @@ public void AddDocumentToUpdate(IDictionary key, Expressi
#region Public Put methods
- ///
- /// Add a single Document to put, using the specified config.
- ///
- /// Document to put.
- /// Configuration to use.
+ ///
public void AddDocumentToPut(Document document, TransactWriteItemOperationConfig operationConfig = null)
{
Items.Add(new ToPutTransactWriteRequestItem
@@ -220,83 +331,49 @@ public void AddDocumentToPut(Document document, TransactWriteItemOperationConfig
#region Public ConditionCheck methods
- ///
- /// Add a single item to condition check, identified by its hash primary key, using the specified condition expression.
- ///
- /// Hash key of the item.
- /// The expression to evaluate for the item.
+ ///
public void AddKeyToConditionCheck(Primitive hashKey, Expression conditionalExpression)
{
AddKeyToConditionCheck(hashKey, new TransactWriteItemOperationConfig { ConditionalExpression = conditionalExpression });
}
- ///
- /// Add a single item to condition check, identified by its hash primary key, using the specified config.
- ///
- /// Hash key of the item.
- /// Configuration to use.
+ ///
public void AddKeyToConditionCheck(Primitive hashKey, TransactWriteItemOperationConfig operationConfig)
{
AddKeyToConditionCheck(hashKey, rangeKey: null, operationConfig);
}
- ///
- /// Add a single item to condition check, identified by its hash-and-range primary key, using the specified condition expression.
- ///
- /// Hash key of the item.
- /// Range key of the item.
- /// The expression to evaluate for the item.
+ ///
public void AddKeyToConditionCheck(Primitive hashKey, Primitive rangeKey, Expression conditionalExpression)
{
AddKeyToConditionCheck(hashKey, rangeKey, new TransactWriteItemOperationConfig { ConditionalExpression = conditionalExpression });
}
- ///
- /// Add a single item to condition check, identified by its hash-and-range primary key, using the specified config.
- ///
- /// Hash key of the item.
- /// Range key of the item.
- /// Configuration to use.
+ ///
public void AddKeyToConditionCheck(Primitive hashKey, Primitive rangeKey, TransactWriteItemOperationConfig operationConfig)
{
AddKeyToConditionCheckHelper(TargetTable.MakeKey(hashKey, rangeKey), operationConfig);
}
- ///
- /// Add a single item to condition check, identified by its key, using the specified condition expression.
- ///
- /// Key of the item.
- /// The expression to evaluate for the item.
+ ///
public void AddKeyToConditionCheck(IDictionary key, Expression conditionalExpression)
{
AddKeyToConditionCheck(key, new TransactWriteItemOperationConfig { ConditionalExpression = conditionalExpression });
}
- ///
- /// Add a single item to condition check, identified by its key, using the specified config.
- ///
- /// Key of the item.
- /// Configuration to use.
+ ///
public void AddKeyToConditionCheck(IDictionary key, TransactWriteItemOperationConfig operationConfig)
{
AddKeyToConditionCheckHelper(TargetTable.MakeKey(key), operationConfig);
}
- ///
- /// Add a single item to condition check, identified by a Document object, using the specified condition expression.
- ///
- /// Document representing the item.
- /// The expression to evaluate for the item.
+ ///
public void AddItemToConditionCheck(Document document, Expression conditionalExpression)
{
AddItemToConditionCheck(document, new TransactWriteItemOperationConfig { ConditionalExpression = conditionalExpression });
}
- ///
- /// Add a single item to condition check, identified by a Document object, using the specified config.
- ///
- /// Document representing the item.
- /// Configuration to use.
+ ///
public void AddItemToConditionCheck(Document document, TransactWriteItemOperationConfig operationConfig)
{
AddKeyToConditionCheckHelper(TargetTable.MakeKey(document), operationConfig);
@@ -451,15 +528,8 @@ private static bool TryFilterDuplicates(Dictionary src, Dictionary
#region Public methods
- ///
- /// Creates a MultiTableDocumentTransactWrite object that is a combination
- /// of the current DocumentTransactWrite and the specified DocumentTransactWrite.
- ///
- /// Other DocumentTransactWrite object.
- ///
- /// MultiTableDocumentTransactWrite consisting of the two DocumentTransactWrite objects.
- ///
- public MultiTableDocumentTransactWrite Combine(DocumentTransactWrite otherTransactionPart)
+ ///
+ public MultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart)
{
return new MultiTableDocumentTransactWrite(this, otherTransactionPart);
}
@@ -468,18 +538,34 @@ public MultiTableDocumentTransactWrite Combine(DocumentTransactWrite otherTransa
}
///
- /// Class for condition checking, putting, updating and/or deleting
+ /// Interface for condition checking, putting, updating and/or deleting
/// multiple items in multiple DynamoDB tables in a transaction.
///
- public partial class MultiTableDocumentTransactWrite
+ public partial interface IMultiTableDocumentTransactWrite
{
- #region Properties
-
///
/// List of DocumentTransactWrite objects to include in the multi-table
/// transaction request.
///
- public List TransactionParts { get; private set; }
+ List TransactionParts { get; }
+
+ ///
+ /// Add a DocumentTransactWrite object to the multi-table transaction request.
+ ///
+ /// DocumentTransactWrite to add.
+ void AddTransactionPart(IDocumentTransactWrite transactionPart);
+ }
+
+ ///
+ /// Class for condition checking, putting, updating and/or deleting
+ /// multiple items in multiple DynamoDB tables in a transaction.
+ ///
+ public partial class MultiTableDocumentTransactWrite : IMultiTableDocumentTransactWrite
+ {
+ #region Properties
+
+ ///
+ public List TransactionParts { get; private set; }
#endregion
@@ -491,12 +577,12 @@ public partial class MultiTableDocumentTransactWrite
/// DocumentTransactWrite objects.
///
/// Collection of DocumentTransactWrite objects.
- public MultiTableDocumentTransactWrite(params DocumentTransactWrite[] transactionParts)
+ public MultiTableDocumentTransactWrite(params IDocumentTransactWrite[] transactionParts)
{
if (transactionParts == null)
throw new ArgumentNullException(nameof(transactionParts));
- TransactionParts = new List(transactionParts);
+ TransactionParts = new List(transactionParts);
}
#endregion
@@ -504,11 +590,8 @@ public MultiTableDocumentTransactWrite(params DocumentTransactWrite[] transactio
#region Public methods
- ///
- /// Add a DocumentTransactWrite object to the multi-table transaction request.
- ///
- /// DocumentTransactWrite to add.
- public void AddTransactionPart(DocumentTransactWrite transactionPart)
+ ///
+ public void AddTransactionPart(IDocumentTransactWrite transactionPart)
{
TransactionParts.Add(transactionPart);
}
@@ -520,13 +603,16 @@ public void AddTransactionPart(DocumentTransactWrite transactionPart)
internal void ExecuteHelper()
{
+ List docTransactionParts = new();
try
{
GetMultiTransactWrite().WriteItems();
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactWrite)}";
+ docTransactionParts = TransactionParts.Select(x => x as DocumentTransactWrite ?? throw new InvalidOperationException(errMsg)).ToList();
}
finally
{
- foreach (var transactionPart in TransactionParts)
+ foreach (var transactionPart in docTransactionParts)
{
if (transactionPart.ConditionCheckFailedItems == null)
transactionPart.ConditionCheckFailedItems = new List();
@@ -537,13 +623,16 @@ internal void ExecuteHelper()
#if AWS_ASYNC_API
internal async Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
+ List docTransactionParts = new();
try
{
await GetMultiTransactWrite().WriteItemsAsync(cancellationToken).ConfigureAwait(false);
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactWrite)}";
+ docTransactionParts = TransactionParts.Select(x => x as DocumentTransactWrite ?? throw new InvalidOperationException(errMsg)).ToList();
}
finally
{
- foreach (var transactionPart in TransactionParts)
+ foreach (var transactionPart in docTransactionParts)
{
if (transactionPart.ConditionCheckFailedItems == null)
transactionPart.ConditionCheckFailedItems = new List();
@@ -554,9 +643,14 @@ internal async Task ExecuteHelperAsync(CancellationToken cancellationToken)
private MultiTransactWrite GetMultiTransactWrite()
{
+ var errMsg = $"All transactionParts must be of type {nameof(DocumentTransactWrite)}";
return new MultiTransactWrite
{
- Items = TransactionParts.SelectMany(x => x.Items).ToList()
+ Items = TransactionParts.SelectMany(x =>
+ {
+ var docTransactWrite = x as DocumentTransactWrite ?? throw new InvalidOperationException(errMsg);
+ return docTransactWrite.Items;
+ }).ToList()
};
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index 1ac032d690ea..f5eb19703137 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -1605,7 +1605,7 @@ public IDocumentTransactGet CreateTransactGet()
/// a transactional condition-check/put/update/delete operation against DynamoDB.
///
/// Empty DocumentTransactWrite object.
- public DocumentTransactWrite CreateTransactWrite()
+ public IDocumentTransactWrite CreateTransactWrite()
{
return new DocumentTransactWrite(this);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactWrite.Async.cs
index 064870c203c2..18b39e01c350 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactWrite.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentTransactWrite.Async.cs
@@ -18,45 +18,41 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for condition checking, putting, updating and/or deleting
- /// multiple items in a single DynamoDB table in a transaction.
- ///
- public partial class DocumentTransactWrite
+ public partial interface IDocumentTransactWrite
{
- #region Public methods
-
///
/// Executes a server call to condition-check/put/update/delete the items specified in a transaction.
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class DocumentTransactWrite : IDocumentTransactWrite
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
- ///
- /// Class for condition checking, putting, updating and/or deleting
- /// multiple items in multiple DynamoDB tables in a transaction.
- ///
- public partial class MultiTableDocumentTransactWrite
+ public partial interface IMultiTableDocumentTransactWrite
{
- #region Public methods
-
///
/// Executes a multi-table transactional condition-check/put/update/delete against all configured DocumentTransactWrite objects.
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class MultiTableDocumentTransactWrite : IMultiTableDocumentTransactWrite
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactWrite.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactWrite.Sync.cs
index 8522a260d843..8054342804e5 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactWrite.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/DocumentTransactWrite.Sync.cs
@@ -15,41 +15,41 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Class for condition checking, putting, updating and/or deleting
- /// multiple items in a single DynamoDB table in a transaction.
- ///
- public partial class DocumentTransactWrite
+ public partial interface IDocumentTransactWrite
{
- #region Public methods
-
///
/// Executes a server call to condition-check/put/update/delete the items specified in a transaction.
///
+ void Execute();
+ }
+
+ public partial class DocumentTransactWrite : IDocumentTransactWrite
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
+ }
- #endregion
+ public partial interface IMultiTableDocumentTransactWrite
+ {
+ ///
+ /// Executes a multi-table transactional condition-check/put/update/delete against all configured DocumentTransactWrite objects.
+ ///
+ void Execute();
}
///
/// Class for condition checking, putting, updating and/or deleting
/// multiple items in multiple DynamoDB tables in a transaction.
///
- public partial class MultiTableDocumentTransactWrite
+ public partial class MultiTableDocumentTransactWrite : IMultiTableDocumentTransactWrite
{
- #region Public methods
-
- ///
- /// Executes a multi-table transactional condition-check/put/update/delete against all configured DocumentTransactWrite objects.
- ///
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
}
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.cs
new file mode 100644
index 000000000000..840bec39e5cc
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.cs
@@ -0,0 +1,113 @@
+using Amazon.DynamoDBv2.DocumentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class DocumentTransactWriteTests
+ {
+ [TestMethod]
+ public void TestMockability_DocumentTransactWrite()
+ {
+ var itemsToPut = new List();
+ var inMemoryTable = new List();
+
+ var docTransactWrite = CreateDocumentTransactWriteMock(itemsToPut, inMemoryTable);
+
+ Assert.AreEqual(0, inMemoryTable.Count);
+ Assert.AreEqual(0, itemsToPut.Count);
+
+ docTransactWrite.AddDocumentToPut(new Document { { "key1", "value1" } });
+ docTransactWrite.AddDocumentToPut(new Document { { "key2", "value2" } });
+ Assert.AreEqual(2, itemsToPut.Count);
+ Assert.AreEqual(0, inMemoryTable.Count);
+
+ docTransactWrite.Execute();
+ Assert.AreEqual(0, itemsToPut.Count);
+ Assert.AreEqual(2, inMemoryTable.Count);
+
+ var firstDoc = inMemoryTable.First();
+ Assert.AreEqual("value1", firstDoc["key1"].AsString());
+
+ var secondDoc = inMemoryTable.Skip(1).First();
+ Assert.AreEqual("value2", secondDoc["key2"].AsString());
+ }
+
+ [TestMethod]
+ public void TestMockability_MultiTableDocumentTransactWrite()
+ {
+ var itemsToPut_table1 = new List();
+ var inMemory_table1 = new List();
+ var transactWrite_table1 = CreateDocumentTransactWriteMock(itemsToPut_table1, inMemory_table1);
+ transactWrite_table1.AddDocumentToPut(new Document { { "key1", "value1" } });
+
+ var itemsToPut_table2 = new List();
+ var inMemory_table2 = new List();
+ var transactWrite_table2 = CreateDocumentTransactWriteMock(itemsToPut_table2, inMemory_table2);
+ transactWrite_table2.AddDocumentToPut(new Document { { "key2", "value2" } });
+
+ var multiTransactWrite = CreateMultiTableDocumentTransactWrite();
+ multiTransactWrite.AddTransactionPart(transactWrite_table1);
+ multiTransactWrite.AddTransactionPart(transactWrite_table2);
+
+ Assert.AreEqual(0, inMemory_table1.Count);
+ Assert.AreEqual(0, inMemory_table2.Count);
+
+ multiTransactWrite.Execute();
+ Assert.AreEqual(1, inMemory_table1.Count);
+ Assert.AreEqual(1, inMemory_table2.Count);
+ Assert.AreEqual("value1", inMemory_table1.First()["key1"].AsString());
+ Assert.AreEqual("value2", inMemory_table2.First()["key2"].AsString());
+ }
+
+ public IDocumentTransactWrite CreateDocumentTransactWriteMock(List itemsToSave, List inMemoryTable)
+ {
+ var transactWrite = new Mock();
+
+ transactWrite
+ .Setup(x => x.AddDocumentToPut(It.IsAny(), It.IsAny()))
+ .Callback((Document item, TransactWriteItemOperationConfig config) => itemsToSave.Add(item));
+
+ transactWrite
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var item in itemsToSave)
+ {
+ inMemoryTable.Add(item);
+ }
+ itemsToSave.Clear();
+ });
+
+ return transactWrite.Object;
+ }
+
+ public IMultiTableDocumentTransactWrite CreateMultiTableDocumentTransactWrite()
+ {
+ var multiTransactWrite = new Mock();
+ var transactionParts = new List();
+
+ multiTransactWrite
+ .Setup(x => x.AddTransactionPart(It.IsAny()))
+ .Callback((IDocumentTransactWrite part) =>
+ {
+ transactionParts.Add(part);
+ });
+
+ multiTransactWrite
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var part in transactionParts)
+ {
+ part.Execute();
+ }
+ });
+
+ return multiTransactWrite.Object;
+ }
+ }
+}
From ad3d8a4f404f72df68483b25c099363c6e7e0917 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Fri, 16 Aug 2024 12:19:05 -0700
Subject: [PATCH 5/7] Add the ability to mock Search operations in Document
model
---
.../Custom/DataModel/ContextInternal.cs | 16 +-
.../DynamoDBv2/Custom/DocumentModel/Search.cs | 166 ++++++++++++------
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 14 +-
.../DocumentModel/_async/Search.Async.cs | 37 ++--
.../Custom/DocumentModel/_bcl/Search.Sync.cs | 33 ++--
.../IntegrationTests/DocumentTests.cs | 2 +-
.../MockabilityTests/DocumentSearchTests.cs | 41 +++++
7 files changed, 207 insertions(+), 102 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
index 447c52c65dcd..86c33c201b02 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
@@ -1178,7 +1178,9 @@ private ContextSearch ConvertScan(IEnumerable conditions, Dyna
IndexName = flatConfig.IndexName,
ConsistentRead = flatConfig.ConsistentRead.GetValueOrDefault(false)
};
- Search scan = table.Scan(scanConfig);
+
+ // table.Scan() returns the ISearch interface but we explicitly cast it to a Search object since we rely on its internal behavior
+ Search scan = table.Scan(scanConfig) as Search;
return new ContextSearch(scan, flatConfig);
}
@@ -1187,7 +1189,9 @@ private ContextSearch ConvertFromScan(ScanOperationConfig scanConfig, DynamoD
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig);
Table table = GetTargetTable(storageConfig, flatConfig);
- Search search = table.Scan(scanConfig);
+
+ // table.Scan() returns the ISearch interface but we explicitly cast it to a Search object since we rely on its internal behavior
+ Search search = table.Scan(scanConfig) as Search;
return new ContextSearch(search, flatConfig);
}
@@ -1196,7 +1200,9 @@ private ContextSearch ConvertFromQuery(QueryOperationConfig queryConfig, Dyna
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig);
Table table = GetTargetTable(storageConfig, flatConfig);
- Search search = table.Query(queryConfig);
+
+ // table.Query() returns the ISearch interface but we explicitly cast it to a Search object since we rely on its internal behavior
+ Search search = table.Query(queryConfig) as Search;
return new ContextSearch(search, flatConfig);
}
@@ -1241,7 +1247,9 @@ private ContextSearch ConvertQueryHelper(DynamoDBFlatConfig currentConfig, It
{
queryConfig.Select = SelectValues.AllProjectedAttributes;
}
- Search query = table.Query(queryConfig);
+
+ // table.Query() returns the ISearch interface but we explicitly cast it to a Search object since we rely on its internal behavior
+ Search query = table.Query(queryConfig) as Search;
return new ContextSearch(query, currentConfig);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Search.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Search.cs
index 6eaef4a68e37..5a1ef0114715 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Search.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Search.cs
@@ -18,7 +18,6 @@
using System.Linq;
using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
using System.Globalization;
#if AWS_ASYNC_API
using System.Threading.Tasks;
@@ -28,41 +27,20 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
///
- /// Search response object
+ /// Represents the interface for a search response
///
-#if NET8_0_OR_GREATER
- [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
-#endif
- public partial class Search
+ public partial interface ISearch
{
- #region Internal constructors
-
- internal Search()
- : this((SearchType)0)
- {
- }
-
- internal Search(SearchType searchMethod)
- {
- SearchMethod = searchMethod;
- Reset();
- }
-
- #endregion
-
-
- #region Public properties
-
///
/// Name of the table being searched
///
- public String TableName { get; internal set; }
+ string TableName { get; }
///
/// Whether to collect GetNextSet and GetRemaining results in Matches property.
/// Default is true. If set to false, Matches will always be empty.
///
- public bool CollectResults { get; internal set; }
+ bool CollectResults { get; }
///
/// Upper limit on the number of items returned.
@@ -71,77 +49,67 @@ internal Search(SearchType searchMethod)
///
/// Maps directly to Limit property on Query and Scan operations.
///
- public int Limit { get; internal set; }
+ int Limit { get; }
///
/// The key expression that is evaluated for each item of a query.
/// This applies only to Query operations.
///
- public Expression KeyExpression { get; set; }
+ Expression KeyExpression { get; set; }
///
/// The filter expression that is evaluated for each item.
/// This applies to Query and Scan operations.
///
- public Expression FilterExpression { get; set; }
+ Expression FilterExpression { get; set; }
///
/// Filter for the search operation
/// This applies to Query and Scan operations.
///
- public Filter Filter { get; internal set; }
+ Filter Filter { get; }
///
/// Conditional operator for the search operation
///
- public ConditionalOperatorValues ConditionalOperator { get; internal set; }
+ ConditionalOperatorValues ConditionalOperator { get; }
///
/// List of attribute names to retrieve
///
- public List AttributesToGet { get; internal set; }
+ List AttributesToGet { get; }
///
/// Flag that, if true, indicates that the search is operating in consistent-read mode
///
- public bool IsConsistentRead { get; internal set; }
+ bool IsConsistentRead { get; }
///
/// Flag that, if true, indicates that the search is traversing backwards
///
- public bool IsBackwardSearch { get; internal set; }
+ bool IsBackwardSearch { get; }
///
/// Flag that, if true, indicates that the search is done
///
- public bool IsDone { get; private set; }
+ bool IsDone { get; }
///
/// Key denoting the starting point of the next set of results
///
- public Dictionary NextKey { get; private set; }
+ Dictionary NextKey { get; }
///
/// Pagination token corresponding to the item where the search operation stopped,
/// inclusive of the previous result set. Use this value to start a new
/// operation to resume search from the next item.
///
- public string PaginationToken
- {
- get
- {
- return Common.ToPaginationToken(NextKey);
- }
- internal set
- {
- NextKey = Common.FromPaginationToken(value);
- }
- }
+ string PaginationToken { get; }
///
/// List of currently found items
///
- public List Matches { get; private set; }
+ List Matches { get; }
///
/// For parallel Scan requests, TotalSegmentsrepresents the total number of segments for a table that is being scanned. Segments
@@ -162,7 +130,7 @@ internal set
///
///
///
- public int TotalSegments { get; set; }
+ int TotalSegments { get; set; }
///
/// For parallel Scan requests, Segment identifies an individual segment to be scanned by an application "worker" (such as a
@@ -182,7 +150,7 @@ internal set
///
///
///
- public int Segment { get; set; }
+ int Segment { get; set; }
///
/// Gets the total number of items that match the search parameters.
@@ -191,16 +159,110 @@ internal set
/// Otherwise, makes a call to DynamoDB to find out the number of
/// matching items, without retrieving the items. Count is then cached.
///
- public int Count { get { return GetCount(); } }
+ int Count { get; }
///
/// Name of the index to query or scan against.
///
- public string IndexName { get; internal set; }
+ string IndexName { get; }
///
/// Enum specifying what data to return from query.
///
+ SelectValues Select { get; }
+ }
+
+ ///
+ /// Search response object
+ ///
+#if NET8_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
+#endif
+ public partial class Search : ISearch
+ {
+ #region Internal constructors
+
+ internal Search()
+ : this((SearchType)0)
+ {
+ }
+
+ internal Search(SearchType searchMethod)
+ {
+ SearchMethod = searchMethod;
+ Reset();
+ }
+
+ #endregion
+
+
+ #region Public properties
+
+ ///
+ public string TableName { get; internal set; }
+
+ ///
+ public bool CollectResults { get; internal set; }
+
+ ///
+ public int Limit { get; internal set; }
+
+ ///
+ public Expression KeyExpression { get; set; }
+
+ ///
+ public Expression FilterExpression { get; set; }
+
+ ///
+ public Filter Filter { get; internal set; }
+
+ ///
+ public ConditionalOperatorValues ConditionalOperator { get; internal set; }
+
+ ///
+ public List AttributesToGet { get; internal set; }
+
+ ///
+ public bool IsConsistentRead { get; internal set; }
+
+ ///
+ public bool IsBackwardSearch { get; internal set; }
+
+ ///
+ public bool IsDone { get; private set; }
+
+ ///
+ public Dictionary NextKey { get; private set; }
+
+ ///
+ public string PaginationToken
+ {
+ get
+ {
+ return Common.ToPaginationToken(NextKey);
+ }
+ internal set
+ {
+ NextKey = Common.FromPaginationToken(value);
+ }
+ }
+
+ ///
+ public List Matches { get; private set; }
+
+ ///
+ public int TotalSegments { get; set; }
+
+ ///
+ public int Segment { get; set; }
+
+ ///
+ public int Count { get { return GetCount(); } }
+
+ ///
+ public string IndexName { get; internal set; }
+
+ ///
public SelectValues Select { get; internal set; }
#endregion
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index f5eb19703137..82d2e322e466 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -1393,7 +1393,7 @@ internal async Task DeleteHelperAsync(Key key, DeleteItemOperationConf
///
/// Filter to apply to the scan.
/// Resultant Search container.
- public Search Scan(ScanFilter filter)
+ public ISearch Scan(ScanFilter filter)
{
return Scan(new ScanOperationConfig { Filter = filter });
}
@@ -1406,7 +1406,7 @@ public Search Scan(ScanFilter filter)
///
/// Expression to apply to the scan.
/// Resultant Search container.
- public Search Scan(Expression filterExpression)
+ public ISearch Scan(Expression filterExpression)
{
ScanOperationConfig config = new ScanOperationConfig
{
@@ -1425,7 +1425,7 @@ public Search Scan(Expression filterExpression)
///
/// Configuration to use.
/// Resultant Search container.
- public Search Scan(ScanOperationConfig config)
+ public ISearch Scan(ScanOperationConfig config)
{
var currentConfig = config ?? new ScanOperationConfig();
@@ -1468,7 +1468,7 @@ public Search Scan(ScanOperationConfig config)
/// Value of the hash key for the query operation.
/// Filter to use.
/// Resultant Search container.
- public Search Query(Primitive hashKey, QueryFilter filter)
+ public ISearch Query(Primitive hashKey, QueryFilter filter)
{
string hashKeyName = this.HashKeys[0];
QueryFilter fullFilter = new QueryFilter(filter);
@@ -1487,7 +1487,7 @@ public Search Query(Primitive hashKey, QueryFilter filter)
/// Value of the hash key for the query operation.
/// Expression to use.
/// Resultant Search container.
- public Search Query(Primitive hashKey, Expression filterExpression)
+ public ISearch Query(Primitive hashKey, Expression filterExpression)
{
string hashKeyName = this.HashKeys[0];
@@ -1511,7 +1511,7 @@ public Search Query(Primitive hashKey, Expression filterExpression)
///
/// Filter to use.
/// Resultant Search container.
- public Search Query(QueryFilter filter)
+ public ISearch Query(QueryFilter filter)
{
return Query(new QueryOperationConfig { Filter = filter });
}
@@ -1524,7 +1524,7 @@ public Search Query(QueryFilter filter)
///
/// Configuration to use.
/// Resultant Search container.
- public Search Query(QueryOperationConfig config)
+ public ISearch Query(QueryOperationConfig config)
{
if (config == null)
throw new ArgumentNullException("config");
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Search.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Search.Async.cs
index 7e34958b7e8f..575fafe3b4f2 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Search.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Search.Async.cs
@@ -14,50 +14,47 @@
*/
#pragma warning disable 1574
-using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-using Amazon.Runtime.Internal;
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Search response object
- ///
- public partial class Search
+ public partial interface ISearch
{
-
- #region Async public
-
///
/// Initiates the asynchronous execution of the GetNextSet operation.
- ///
+ ///
/// If there are more items in the Scan/Query, PaginationToken will be
/// set and can be consumed in a new Scan/Query operation to resume
/// retrieving items from this point.
- ///
+ ///
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetNextSetHelperAsync(cancellationToken);
- }
+ Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetRemaining operation.
- ///
+ ///
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
+ Task> GetRemainingAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class Search : ISearch
+ {
+ ///
+ public Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetNextSetHelperAsync(cancellationToken);
+ }
+
+ ///
public Task> GetRemainingAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return GetRemainingHelperAsync(cancellationToken);
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Search.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Search.Sync.cs
index 7b1816f8fc73..b2a916ccdb54 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Search.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Search.Sync.cs
@@ -13,44 +13,41 @@
* permissions and limitations under the License.
*/
-using System;
using System.Collections.Generic;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-
namespace Amazon.DynamoDBv2.DocumentModel
{
- ///
- /// Search response object
- ///
- public partial class Search
+ public partial interface ISearch
{
- #region Public methods
-
///
/// Retrieves the next set (page) of results
- ///
+ ///
/// If there are more items in the Scan/Query, PaginationToken will be
/// set and can be consumed in a new Scan/Query operation to resume
/// retrieving items from this point.
///
/// Next set of Documents matching the search parameters
- public List GetNextSet()
- {
- return GetNextSetHelper();
- }
+ List GetNextSet();
///
/// Retrieves all the remaining results
///
/// List of Documents matching the search parameters
+ List GetRemaining();
+ }
+
+ public partial class Search : ISearch
+ {
+ ///
+ public List GetNextSet()
+ {
+ return GetNextSetHelper();
+ }
+
+ ///
public List GetRemaining()
{
return GetRemainingHelper();
}
-
- #endregion
-
}
}
diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs
index 86bad3e5ca89..64694bae6e21 100644
--- a/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs
+++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs
@@ -294,7 +294,7 @@ private void TestPagination(Table hashRangeTable)
}
}
- private static int VerifyPagination(Search search, List tokens)
+ private static int VerifyPagination(ISearch search, List tokens)
{
int count = 0;
do
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs
new file mode 100644
index 000000000000..6dafba11541f
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs
@@ -0,0 +1,41 @@
+using Amazon.DynamoDBv2.DocumentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class DocumentSearchTests
+ {
+ [TestMethod]
+ public void TestMockability_DocumentSearch()
+ {
+ var search = CreateSearchMock(new List()
+ {
+ new Document(){ {"id", 1}, {"name", "Bob"} },
+ new Document(){ {"id", 2}, {"name", "Tom"} }
+ });
+
+ var results = search.GetNextSet();
+ Assert.AreEqual(2, results.Count);
+
+ Assert.AreEqual(1, results[0]["id"].AsInt());
+ Assert.AreEqual("Bob", results[0]["name"].AsString());
+
+ Assert.AreEqual(2, results[1]["id"].AsInt());
+ Assert.AreEqual("Tom", results[1]["name"].AsString());
+ }
+
+ public ISearch CreateSearchMock(List dummyResults)
+ {
+ var search = new Mock();
+
+ search
+ .Setup(x => x.GetNextSet())
+ .Returns(dummyResults);
+
+ return search.Object;
+ }
+ }
+}
From f72f1948dfbd1f58c4bf7d4784a64a1d03cc43db Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Fri, 16 Aug 2024 15:23:12 -0700
Subject: [PATCH 6/7] Add the ability to mock Table operations in Document
model
---
.../Custom/DataModel/ContextInternal.cs | 2 +-
.../Custom/DataModel/_bcl/Context.Sync.cs | 6 +-
.../DataModel/_bcl/IDynamoDBContext.Sync.cs | 6 +-
.../DataModel/_netstandard/Context.Sync.cs | 9 +-
.../_netstandard/IDynamoDBContext.Sync.cs | 8 +-
.../Custom/DocumentModel/DocumentBatchGet.cs | 4 +-
.../DocumentModel/DocumentBatchWrite.cs | 4 +-
.../DocumentModel/DocumentTransactGet.cs | 4 +-
.../DocumentModel/DocumentTransactWrite.cs | 4 +-
.../DynamoDBv2/Custom/DocumentModel/Table.cs | 392 ++++++++++++------
.../DocumentModel/_async/Table.Async.cs | 282 ++++++++-----
.../Custom/DocumentModel/_bcl/Table.Sync.cs | 371 ++++++++++-------
.../DynamoDBv2/IntegrationTests/Cache.cs | 2 +-
.../IntegrationTests/DocumentTests.cs | 72 ++--
.../DynamoDBv2/IntegrationTests/Extensions.cs | 2 +-
.../DynamoDBv2/IntegrationTests/JSONTests.cs | 6 +-
.../DynamoDBv2/IntegrationTests/TTLTests.cs | 8 +-
.../MockabilityTests/DocumentBatchGetTests.cs | 6 +-
.../DocumentBatchWriteTests.cs | 6 +-
.../MockabilityTests/DocumentSearchTests.cs | 43 +-
.../DocumentTransactGetTests.cs | 6 +-
.../DocumentTransactWriteTests.cs | 6 +-
22 files changed, 787 insertions(+), 462 deletions(-)
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
index 86c33c201b02..2c94bd9c32aa 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs
@@ -189,7 +189,7 @@ internal Table GetUnconfiguredTable(string tableName, bool disableFetchingTableM
var emptyConfig = new TableConfig(tableName, conversion: null, consumer: Table.DynamoDBConsumer.DataModel,
storeAsEpoch: null, isEmptyStringValueEnabled: false, metadataCachingMode: Config.MetadataCachingMode);
- table = Table.LoadTable(Client, emptyConfig);
+ table = Table.LoadTable(Client, emptyConfig) as Table;
tablesMap[tableName] = table;
return table;
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
index 4207dc5833c6..612209360b23 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
@@ -348,20 +348,20 @@ public IEnumerable FromQuery(QueryOperationConfig queryConfig, FromQueryCo
#region Table methods
///
- public Table GetTargetTable()
+ public ITable GetTargetTable()
{
return GetTargetTable((GetTargetTableConfig)null);
}
///
[Obsolete("Use the GetTargetTable overload that takes GetTargetTableConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to GetTargetTable.")]
- public Table GetTargetTable(DynamoDBOperationConfig operationConfig = null)
+ public ITable GetTargetTable(DynamoDBOperationConfig operationConfig = null)
{
return GetTargetTableInternal(new DynamoDBFlatConfig(operationConfig, Config));
}
///
- public Table GetTargetTable(GetTargetTableConfig getTargetTableConfig)
+ public ITable GetTargetTable(GetTargetTableConfig getTargetTableConfig)
{
return GetTargetTableInternal(new DynamoDBFlatConfig(getTargetTableConfig?.ToDynamoDBOperationConfig(), Config));
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
index 1c8c6b36d67b..e500bcb20ce8 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
@@ -593,7 +593,7 @@ partial interface IDynamoDBContext
///
/// Type to retrieve table for
/// Table object
- Table GetTargetTable();
+ ITable GetTargetTable();
///
/// Retrieves the target table for the specified type
@@ -602,7 +602,7 @@ partial interface IDynamoDBContext
/// Config object which can be used to override that table used.
/// Table object
[Obsolete("Use the GetTargetTable overload that takes GetTargetTableConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to GetTargetTable.")]
- Table GetTargetTable(DynamoDBOperationConfig operationConfig = null);
+ ITable GetTargetTable(DynamoDBOperationConfig operationConfig = null);
///
/// Retrieves the target table for the specified type
@@ -610,7 +610,7 @@ partial interface IDynamoDBContext
/// Type to retrieve table for
/// Config object that can be used to override properties on the table's context for this request.
/// Table object
- Table GetTargetTable(GetTargetTableConfig getTargetTableConfig);
+ ITable GetTargetTable(GetTargetTableConfig getTargetTableConfig);
#endregion
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs
index 085925e38fa1..d268cea1fc2f 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs
@@ -14,11 +14,8 @@
*/
using System;
-using System.Collections.Generic;
-using System.Linq;
using Amazon.DynamoDBv2.DocumentModel;
-using Amazon.DynamoDBv2.Model;
namespace Amazon.DynamoDBv2.DataModel
{
@@ -27,20 +24,20 @@ public partial class DynamoDBContext : IDynamoDBContext
#region Table methods
///
- public Table GetTargetTable()
+ public ITable GetTargetTable()
{
return GetTargetTableInternal(new DynamoDBFlatConfig(null, Config));
}
///
[Obsolete("Use the GetTargetTable overload that takes GetTargetTableConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to GetTargetTable.")]
- public Table GetTargetTable(DynamoDBOperationConfig operationConfig = null)
+ public ITable GetTargetTable(DynamoDBOperationConfig operationConfig = null)
{
return GetTargetTableInternal(new DynamoDBFlatConfig(operationConfig, Config));
}
///
- public Table GetTargetTable(GetTargetTableConfig getTargetTableConfig)
+ public ITable GetTargetTable(GetTargetTableConfig getTargetTableConfig)
{
return GetTargetTableInternal(new DynamoDBFlatConfig(getTargetTableConfig?.ToDynamoDBOperationConfig(), Config));
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs
index 48a267e7636a..61c921feafcf 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs
@@ -14,10 +14,8 @@
*/
using System;
-using System.Collections.Generic;
using Amazon.DynamoDBv2.DocumentModel;
-using Amazon.DynamoDBv2.Model;
namespace Amazon.DynamoDBv2.DataModel
{
@@ -34,7 +32,7 @@ partial interface IDynamoDBContext
///
/// Type to retrieve table for
/// Table object
- Table GetTargetTable();
+ ITable GetTargetTable();
///
/// Retrieves the target table for the specified type
@@ -42,14 +40,14 @@ partial interface IDynamoDBContext
/// Type to retrieve table for
/// Table object
[Obsolete("Use the GetTargetTable overload that takes GetTargetTableConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to GetTargetTable.")]
- Table GetTargetTable(DynamoDBOperationConfig operationConfig = null);
+ ITable GetTargetTable(DynamoDBOperationConfig operationConfig = null);
///
/// Retrieves the target table for the specified type
///
/// Type to retrieve table for
/// Table object
- Table GetTargetTable(GetTargetTableConfig getTargetTableConfig);
+ ITable GetTargetTable(GetTargetTableConfig getTargetTableConfig);
#endregion
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
index 8a9e84060940..aed84740d092 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchGet.cs
@@ -78,7 +78,7 @@ public partial interface IDocumentBatchGet
/// MultiTableDocumentBatchGet consisting of the two DocumentBatchGet
/// objects.
///
- MultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch);
+ IMultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch);
}
///
@@ -147,7 +147,7 @@ public void AddKey(IDictionary key)
}
///
- public MultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch)
+ public IMultiTableDocumentBatchGet Combine(IDocumentBatchGet otherBatch)
{
return new MultiTableDocumentBatchGet(this, otherBatch);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
index 4557db28b48f..63122f863ab9 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs
@@ -70,7 +70,7 @@ public partial interface IDocumentBatchWrite
/// MultiTableDocumentBatchWrite consisting of the two DocumentBatchWrite
/// objects.
///
- MultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch);
+ IMultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch);
}
///
@@ -146,7 +146,7 @@ public void AddDocumentToPut(Document document)
#region Public methods
///
- public MultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch)
+ public IMultiTableDocumentBatchWrite Combine(IDocumentBatchWrite otherBatch)
{
return new MultiTableDocumentBatchWrite(this, otherBatch);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
index 75057a6b9e89..8a77e44bf89e 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs
@@ -96,7 +96,7 @@ public partial interface IDocumentTransactGet
///
/// MultiTableDocumentTransactGet consisting of the two DocumentTransactGet objects.
///
- MultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart);
+ IMultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart);
}
///
@@ -174,7 +174,7 @@ public void AddKey(IDictionary key, TransactGetItemOperat
}
///
- public MultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart)
+ public IMultiTableDocumentTransactGet Combine(IDocumentTransactGet otherTransactionPart)
{
return new MultiTableDocumentTransactGet(this, otherTransactionPart);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
index da0a29f542ab..08cfc6d75600 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs
@@ -197,7 +197,7 @@ public partial interface IDocumentTransactWrite
///
/// MultiTableDocumentTransactWrite consisting of the two DocumentTransactWrite objects.
///
- MultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart);
+ IMultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart);
}
///
@@ -529,7 +529,7 @@ private static bool TryFilterDuplicates(Dictionary src, Dictionary
#region Public methods
///
- public MultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart)
+ public IMultiTableDocumentTransactWrite Combine(IDocumentTransactWrite otherTransactionPart)
{
return new MultiTableDocumentTransactWrite(this, otherTransactionPart);
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
index 82d2e322e466..80c7ed94456e 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
@@ -30,6 +30,221 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
+ ///
+ /// This represents the table interface when using the Document API. It is used to Get documents from the DynamoDB table
+ /// and write documents back to the DynamoDB table.
+ ///
+ public partial interface ITable
+ {
+ #region Public properties
+
+ ///
+ /// Name of the table.
+ ///
+ string TableName { get; }
+
+ ///
+ /// Keys of the table.
+ ///
+ Dictionary Keys { get; }
+
+ ///
+ /// Global secondary indexes of the table.
+ ///
+ Dictionary GlobalSecondaryIndexes { get; }
+
+ ///
+ /// Local secondary indexes of the table.
+ ///
+ Dictionary LocalSecondaryIndexes { get; }
+
+ ///
+ /// Names of the local secondary indexes of the table.
+ ///
+ List LocalSecondaryIndexNames { get; }
+
+ ///
+ /// Names of the global secondary indexes of the table.
+ ///
+ List GlobalSecondaryIndexNames { get; }
+
+ ///
+ /// List of keys on the table marked HASH
+ ///
+ List HashKeys { get; }
+
+ ///
+ /// List of keys on the table marked RANGE
+ ///
+ List RangeKeys { get; }
+
+ ///
+ /// List of key attributes on the table.
+ ///
+ public List Attributes { get; set; }
+
+ #endregion
+
+ #region Conversion methods
+
+ ///
+ /// Creates a Document from an attribute map.
+ ///
+ /// Map of attribute names to attribute values.
+ /// Document representing the data.
+ Document FromAttributeMap(Dictionary data);
+
+ ///
+ /// Creates a map of attribute names mapped to AttributeValue objects.
+ /// Converts .NET types using the conversion specified in this Table.
+ ///
+ ///
+ Dictionary ToAttributeMap(Document doc);
+
+ ///
+ /// Creates a map of attribute names mapped to ExpectedAttributeValue objects.
+ ///
+ ///
+ Dictionary ToExpectedAttributeMap(Document doc);
+
+ ///
+ /// Creates a map of attribute names mapped to AttributeValueUpdate objects.
+ ///
+ ///
+ /// If true, only attributes that have been changed will be in the map.
+ ///
+ Dictionary ToAttributeUpdateMap(Document doc, bool changedAttributesOnly);
+
+
+ #endregion
+
+ #region Scan
+
+ ///
+ /// Initiates a Search object to Scan a DynamoDB table, with the
+ /// specified filter.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Filter to apply to the scan.
+ /// Resultant Search container.
+ ISearch Scan(ScanFilter filter);
+
+ ///
+ /// Initiates a Search object to Scan a DynamoDB table, with the
+ /// specified expression.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Expression to apply to the scan.
+ /// Resultant Search container.
+ ISearch Scan(Expression filterExpression);
+
+
+ ///
+ /// Initiates a Search object to Scan a DynamoDB table, with the
+ /// specified config.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Configuration to use.
+ /// Resultant Search container.
+ ISearch Scan(ScanOperationConfig config);
+
+ #endregion
+
+ #region Query
+
+ ///
+ /// Initiates a Search object to Query a DynamoDB table, with the
+ /// specified hash primary key and filter.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Value of the hash key for the query operation.
+ /// Filter to use.
+ /// Resultant Search container.
+ ISearch Query(Primitive hashKey, QueryFilter filter);
+
+
+ ///
+ /// Initiates a Search object to Query a DynamoDB table, with the
+ /// specified hash primary key and expression.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Value of the hash key for the query operation.
+ /// Expression to use.
+ /// Resultant Search container.
+ ISearch Query(Primitive hashKey, Expression filterExpression);
+
+ ///
+ /// Initiates a Search object to Query a DynamoDB table, with the
+ /// specified filter.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Filter to use.
+ /// Resultant Search container.
+ ISearch Query(QueryFilter filter);
+
+ ///
+ /// Initiates a Search object to Query a DynamoDB table, with the
+ /// specified config.
+ ///
+ /// No calls are made until the Search object is used.
+ ///
+ /// Configuration to use.
+ /// Resultant Search container.
+ ISearch Query(QueryOperationConfig config);
+
+ #endregion
+
+ #region BatchGet
+
+ ///
+ /// Creates a DocumentBatchGet object for the current table, allowing
+ /// a batch-get operation against DynamoDB.
+ ///
+ /// Empty DocumentBatchGet object.
+ IDocumentBatchGet CreateBatchGet();
+
+ #endregion
+
+ #region BatchWrite
+
+ ///
+ /// Creates a DocumentBatchWrite object for the current table, allowing
+ /// a batch-put/delete operation against DynamoDB.
+ ///
+ /// Empty DocumentBatchWrite object.
+ IDocumentBatchWrite CreateBatchWrite();
+
+ #endregion
+
+ #region TransactGet
+
+ ///
+ /// Creates a DocumentTransactGet object for the current table, allowing
+ /// a transactional get operation against DynamoDB.
+ ///
+ /// Empty DocumentTransactGet object.
+ IDocumentTransactGet CreateTransactGet();
+
+ #endregion
+
+ #region TransactWrite
+
+ ///
+ /// Creates a DocumentTransactWrite object for the current table, allowing
+ /// a transactional condition-check/put/update/delete operation against DynamoDB.
+ ///
+ /// Empty DocumentTransactWrite object.
+ IDocumentTransactWrite CreateTransactWrite();
+
+ #endregion
+ }
+
///
/// The Table class is the starting object when using the Document API. It is used to Get documents from the DynamoDB table
/// and write documents back to the DynamoDB table.
@@ -37,7 +252,7 @@ namespace Amazon.DynamoDBv2.DocumentModel
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
#endif
- public partial class Table
+ public partial class Table : ITable
{
#region Private/internal members
@@ -60,49 +275,31 @@ internal enum DynamoDBConsumer
#region Public properties
- ///
- /// Name of the table.
- ///
+ ///
public string TableName { get { return Config.TableName; } }
- ///
- /// Keys of the table.
- ///
+ ///
public Dictionary Keys { get; private set; }
- ///
- /// Global secondary indexes of the table.
- ///
+ ///
public Dictionary GlobalSecondaryIndexes { get; private set; }
- ///
- /// Local secondary indexes of the table.
- ///
+ ///
public Dictionary LocalSecondaryIndexes { get; private set; }
- ///
- /// Names of the local secondary indexes of the table.
- ///
+ ///
public List LocalSecondaryIndexNames { get; private set; }
- ///
- /// Names of the global secondary indexes of the table.
- ///
+ ///
public List GlobalSecondaryIndexNames { get; private set; }
- ///
- /// List of keys on the table marked HASH
- ///
+ ///
public List HashKeys { get; private set; }
- ///
- /// List of keys on the table marked RANGE
- ///
+ ///
public List RangeKeys { get; private set; }
- ///
- /// List of key attributes on the table.
- ///
+ ///
public List Attributes { get; set; }
#endregion
@@ -443,7 +640,7 @@ public static void ClearTableCache()
/// Client to use to access DynamoDB.
/// Configuration to use for the table.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, TableConfig config)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, TableConfig config)
{
Table table = new Table(ddbClient, config);
var tableDescriptionCache = table.GetTableDescriptionCache();
@@ -648,7 +845,7 @@ internal static Table CreateTableFromItemStorageConfig(IAmazonDynamoDB client, T
/// Client to use to access DynamoDB.
/// Name of the table.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName)
{
return LoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, false);
}
@@ -663,7 +860,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName)
/// Name of the table.
/// Conversion to use for converting .NET values to DynamoDB values.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion)
{
return LoadTable(ddbClient, tableName, conversion, false);
}
@@ -678,7 +875,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
/// Name of the table.
/// If the property is false, empty string values will be interpreted as null values.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled)
{
return LoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, isEmptyStringValueEnabled);
}
@@ -694,7 +891,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool
/// Conversion to use for converting .NET values to DynamoDB values.
/// If the property is false, empty string values will be interpreted as null values.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled)
{
var config = new TableConfig(tableName, conversion, DynamoDBConsumer.DocumentModel, storeAsEpoch: null, isEmptyStringValueEnabled: isEmptyStringValueEnabled, metadataCachingMode: MetadataCachingMode.Default);
@@ -715,7 +912,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
/// requests. This controls how the cache key is derived, which influences when the SDK will call
/// IAmazonDynamoDB.DescribeTable(string) internally to populate the cache.
/// Table object representing the specified table.
- public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, MetadataCachingMode metadataCachingMode)
+ public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, MetadataCachingMode metadataCachingMode)
{
var config = new TableConfig(tableName, conversion, DynamoDBConsumer.DocumentModel, storeAsEpoch: null, isEmptyStringValueEnabled: isEmptyStringValueEnabled, metadataCachingMode: metadataCachingMode);
@@ -736,7 +933,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
///
/// True if table was successfully loaded; otherwise false.
///
- public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out Table table)
+ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out ITable table)
{
return TryLoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, false, out table);
}
@@ -754,7 +951,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out
///
/// True if table was successfully loaded; otherwise false.
///
- public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, out Table table)
+ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, out ITable table)
{
return TryLoadTable(ddbClient, tableName, conversion, false, out table);
}
@@ -772,7 +969,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, Dyn
///
/// True if table was successfully loaded; otherwise false.
///
- public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled, out Table table)
+ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled, out ITable table)
{
return TryLoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, isEmptyStringValueEnabled, out table);
}
@@ -791,7 +988,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, boo
///
/// True if table was successfully loaded; otherwise false.
///
- public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, out Table table)
+ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, out ITable table)
{
return TryLoadTable(ddbClient, tableName, conversion, isEmptyStringValueEnabled, MetadataCachingMode.Default, out table);
}
@@ -818,7 +1015,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient,
DynamoDBEntryConversion conversion,
bool isEmptyStringValueEnabled,
MetadataCachingMode? metadataCachingMode,
- out Table table)
+ out ITable table)
{
var config = new TableConfig(tableName,
conversion,
@@ -842,11 +1039,12 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient,
///
/// True if table was successfully loaded; otherwise false.
///
- public static bool TryLoadTable(IAmazonDynamoDB ddbClient, TableConfig config, out Table table)
+ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, TableConfig config, out ITable table)
{
if (config == null)
throw new ArgumentNullException("config");
+#pragma warning disable CA1031 // Do not catch general exception types
try
{
table = LoadTable(ddbClient, config);
@@ -857,46 +1055,31 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, TableConfig config, o
table = null;
return false;
}
+#pragma warning restore CA1031 // Do not catch general exception types
}
#endregion
#region Conversion methods
- ///
- /// Creates a Document from an attribute map.
- ///
- /// Map of attribute names to attribute values.
- /// Document representing the data.
+ ///
public Document FromAttributeMap(Dictionary data)
{
return Document.FromAttributeMap(data, this.StoreAsEpoch);
}
- ///
- /// Creates a map of attribute names mapped to AttributeValue objects.
- /// Converts .NET types using the conversion specified in this Table.
- ///
- ///
+ ///
public Dictionary ToAttributeMap(Document doc)
{
return doc.ToAttributeMap(this.Conversion, this.StoreAsEpoch, this.IsEmptyStringValueEnabled);
}
- ///
- /// Creates a map of attribute names mapped to ExpectedAttributeValue objects.
- ///
- ///
+ ///
public Dictionary ToExpectedAttributeMap(Document doc)
{
return doc.ToExpectedAttributeMap(this.Conversion, this.StoreAsEpoch, this.IsEmptyStringValueEnabled);
}
- ///
- /// Creates a map of attribute names mapped to AttributeValueUpdate objects.
- ///
- ///
- /// If true, only attributes that have been changed will be in the map.
- ///
+ ///
public Dictionary ToAttributeUpdateMap(Document doc, bool changedAttributesOnly)
{
return doc.ToAttributeUpdateMap(this.Conversion, changedAttributesOnly, this.StoreAsEpoch, this.IsEmptyStringValueEnabled);
@@ -1385,27 +1568,13 @@ internal async Task DeleteHelperAsync(Key key, DeleteItemOperationConf
#region Scan
- ///
- /// Initiates a Search object to Scan a DynamoDB table, with the
- /// specified filter.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Filter to apply to the scan.
- /// Resultant Search container.
+ ///
public ISearch Scan(ScanFilter filter)
{
return Scan(new ScanOperationConfig { Filter = filter });
}
- ///
- /// Initiates a Search object to Scan a DynamoDB table, with the
- /// specified expression.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Expression to apply to the scan.
- /// Resultant Search container.
+ ///
public ISearch Scan(Expression filterExpression)
{
ScanOperationConfig config = new ScanOperationConfig
@@ -1417,14 +1586,7 @@ public ISearch Scan(Expression filterExpression)
}
- ///
- /// Initiates a Search object to Scan a DynamoDB table, with the
- /// specified config.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Configuration to use.
- /// Resultant Search container.
+ ///
public ISearch Scan(ScanOperationConfig config)
{
var currentConfig = config ?? new ScanOperationConfig();
@@ -1459,15 +1621,7 @@ public ISearch Scan(ScanOperationConfig config)
#region Query
- ///
- /// Initiates a Search object to Query a DynamoDB table, with the
- /// specified hash primary key and filter.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Value of the hash key for the query operation.
- /// Filter to use.
- /// Resultant Search container.
+ ///
public ISearch Query(Primitive hashKey, QueryFilter filter)
{
string hashKeyName = this.HashKeys[0];
@@ -1478,15 +1632,7 @@ public ISearch Query(Primitive hashKey, QueryFilter filter)
}
- ///
- /// Initiates a Search object to Query a DynamoDB table, with the
- /// specified hash primary key and expression.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Value of the hash key for the query operation.
- /// Expression to use.
- /// Resultant Search container.
+ ///
public ISearch Query(Primitive hashKey, Expression filterExpression)
{
string hashKeyName = this.HashKeys[0];
@@ -1503,27 +1649,13 @@ public ISearch Query(Primitive hashKey, Expression filterExpression)
return Query(config);
}
- ///
- /// Initiates a Search object to Query a DynamoDB table, with the
- /// specified filter.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Filter to use.
- /// Resultant Search container.
+ ///
public ISearch Query(QueryFilter filter)
{
return Query(new QueryOperationConfig { Filter = filter });
}
- ///
- /// Initiates a Search object to Query a DynamoDB table, with the
- /// specified config.
- ///
- /// No calls are made until the Search object is used.
- ///
- /// Configuration to use.
- /// Resultant Search container.
+ ///
public ISearch Query(QueryOperationConfig config)
{
if (config == null)
@@ -1555,11 +1687,7 @@ public ISearch Query(QueryOperationConfig config)
#region BatchGet
- ///
- /// Creates a DocumentBatchGet object for the current table, allowing
- /// a batch-get operation against DynamoDB.
- ///
- /// Empty DocumentBatchGet object.
+ ///
public IDocumentBatchGet CreateBatchGet()
{
return new DocumentBatchGet(this);
@@ -1570,11 +1698,7 @@ public IDocumentBatchGet CreateBatchGet()
#region BatchWrite
- ///
- /// Creates a DocumentBatchWrite object for the current table, allowing
- /// a batch-put/delete operation against DynamoDB.
- ///
- /// Empty DocumentBatchWrite object.
+ ///
public IDocumentBatchWrite CreateBatchWrite()
{
return new DocumentBatchWrite(this);
@@ -1585,11 +1709,7 @@ public IDocumentBatchWrite CreateBatchWrite()
#region TransactGet
- ///
- /// Creates a DocumentTransactGet object for the current table, allowing
- /// a transactional get operation against DynamoDB.
- ///
- /// Empty DocumentTransactGet object.
+ ///
public IDocumentTransactGet CreateTransactGet()
{
return new DocumentTransactGet(this);
@@ -1600,11 +1720,7 @@ public IDocumentTransactGet CreateTransactGet()
#region TransactWrite
- ///
- /// Creates a DocumentTransactWrite object for the current table, allowing
- /// a transactional condition-check/put/update/delete operation against DynamoDB.
- ///
- /// Empty DocumentTransactWrite object.
+ ///
public IDocumentTransactWrite CreateTransactWrite()
{
return new DocumentTransactWrite(this);
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Table.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Table.Async.cs
index c29cc415c372..adca09ba7bef 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Table.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/Table.Async.cs
@@ -28,7 +28,7 @@
namespace Amazon.DynamoDBv2.DocumentModel
{
- public partial class Table
+ public partial interface ITable
{
#region PutItemAsync
@@ -39,11 +39,7 @@ public partial class Table
/// Document to save.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task PutItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken))
- {
- return PutItemHelperAsync(doc, null, cancellationToken);
- }
-
+ Task PutItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the PutItem operation.
@@ -53,10 +49,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task PutItemAsync(Document doc, PutItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return PutItemHelperAsync(doc, config, cancellationToken);
- }
+ Task PutItemAsync(Document doc, PutItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
#endregion
@@ -68,10 +61,7 @@ public partial class Table
/// Hash key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(hashKey, null), null, cancellationToken);
- }
+ Task GetItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetItem operation.
@@ -80,11 +70,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(Primitive hashKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(hashKey, null), config, cancellationToken);
- }
-
+ Task GetItemAsync(Primitive hashKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetItem operation.
@@ -93,10 +79,7 @@ public partial class Table
/// Range key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(hashKey, rangeKey), null, cancellationToken);
- }
+ Task GetItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetItem operation.
@@ -106,10 +89,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(hashKey, rangeKey), config, cancellationToken);
- }
+ Task GetItemAsync(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetItem operation.
@@ -117,10 +97,7 @@ public partial class Table
/// Ley of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(key), null, cancellationToken);
- }
+ Task GetItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the GetItem operation.
@@ -129,10 +106,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task GetItemAsync(IDictionary key, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return GetItemHelperAsync(MakeKey(key), config, cancellationToken);
- }
+ Task GetItemAsync(IDictionary key, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
#endregion
@@ -144,10 +118,7 @@ public partial class Table
/// Attributes to update.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, null, null, null, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -156,10 +127,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, null, null, config, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -168,10 +136,7 @@ public partial class Table
/// Key of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, IDictionary key, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, MakeKey(key), null, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, IDictionary key, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -181,10 +146,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, IDictionary key, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, MakeKey(key), config, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, IDictionary key, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -193,10 +155,7 @@ public partial class Table
/// Hash key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, hashKey, null, null, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -206,10 +165,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, Primitive hashKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, hashKey, null, config, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, Primitive hashKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -219,10 +175,7 @@ public partial class Table
/// Range key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, hashKey, rangeKey, null, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the UpdateItem operation.
@@ -233,10 +186,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return UpdateHelperAsync(doc, hashKey, rangeKey, config, cancellationToken);
- }
+ Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
#endregion
@@ -249,10 +199,7 @@ public partial class Table
/// Document to delete.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task DeleteItemAsync(Document document, CancellationToken cancellationToken = default(CancellationToken))
- {
- return DeleteHelperAsync(MakeKey(document), null, cancellationToken);
- }
+ Task DeleteItemAsync(Document document, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the DeleteItem operation.
@@ -261,10 +208,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task DeleteItemAsync(Document document, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return DeleteHelperAsync(MakeKey(document), config, cancellationToken);
- }
+ Task DeleteItemAsync(Document document, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the DeleteItem operation.
@@ -272,10 +216,7 @@ public partial class Table
/// Hash key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task DeleteItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return DeleteHelperAsync(MakeKey(hashKey, null), null, cancellationToken);
- }
+ Task DeleteItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the DeleteItem operation.
@@ -284,10 +225,7 @@ public partial class Table
/// Configuration to use.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task DeleteItemAsync(Primitive hashKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken))
- {
- return DeleteHelperAsync(MakeKey(hashKey, null), config, cancellationToken);
- }
+ Task DeleteItemAsync(Primitive hashKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the DeleteItem operation.
@@ -296,10 +234,7 @@ public partial class Table
/// Range key element of the document.
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- public Task DeleteItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken))
- {
- return DeleteHelperAsync(MakeKey(hashKey, rangeKey), null, cancellationToken);
- }
+ Task DeleteItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken));
///
/// Initiates the asynchronous execution of the DeleteItem operation.
@@ -309,10 +244,7 @@ public partial class Table
///