From ab2816a82ada1dce3ecd6d4f222dee747d253de5 Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Tue, 6 Aug 2024 10:26:31 -0700 Subject: [PATCH 1/7] Add the ability to mock BatchGet and MultiTableBatchGet operations (#3407) --- .../DynamoDBv2/Custom/DataModel/BatchGet.cs | 305 ++++++++---------- .../DynamoDBv2/Custom/DataModel/Context.cs | 38 +-- .../Custom/DataModel/IDynamoDBContext.cs | 15 +- .../Custom/DataModel/_async/BatchGet.Async.cs | 47 ++- .../Custom/DataModel/_async/Context.Async.cs | 28 +- .../_async/IDynamoDBContext.Async.cs | 13 +- .../Custom/DataModel/_bcl/BatchGet.Sync.cs | 47 ++- .../Custom/DataModel/_bcl/Context.Sync.cs | 13 +- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 4 +- .../Custom/MockabilityTests/BatchGetTests.cs | 167 ++++++++++ 10 files changed, 384 insertions(+), 293 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGet.cs index 29379dd4a929..7dae11417f1c 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGet.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGet.cs @@ -14,11 +14,9 @@ */ using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; using Amazon.DynamoDBv2.DocumentModel; + #if AWS_ASYNC_API using System.Threading.Tasks; #endif @@ -27,163 +25,151 @@ namespace Amazon.DynamoDBv2.DataModel { /// - /// Represents a non-generic object for retrieving a batch of items + /// Represents a non-generic interface for retrieving a batch of items /// from a single DynamoDB table /// - public abstract partial class BatchGet + public partial interface IBatchGet { - #region Internal/protected properties - /// - /// Gets and sets the UntypedResults property. + /// Returns the total number of keys associated with this Batch request. /// - protected List UntypedResults { get; set; } - internal DynamoDBContext Context { get; set; } - internal DynamoDBFlatConfig Config { get; set; } - internal List Keys { get; set; } - internal DocumentBatchGet DocumentBatch { get; set; } - internal ItemStorageConfig ItemStorageConfig { get; set; } - - #endregion - - - #region Constructor - - internal BatchGet(DynamoDBContext context, DynamoDBFlatConfig config) - { - Context = context; - Config = config; - Keys = new List(); - } - - #endregion - - - #region Public properties + public int TotalKeys { get; } /// - /// List of results retrieved from DynamoDB. - /// Populated after Execute is called. + /// List of non-generic results retrieved from DynamoDB. /// - public List Results { get { return UntypedResults; } } + /// + /// This is only populated after a call to Execute. + /// + List UntypedResults { get; } /// /// If set to true, a consistent read is issued. Otherwise eventually-consistent is used. /// - public bool ConsistentRead { get; set; } - - #endregion + /// + /// Refer to the + /// Read Consistency topic in the DynamoDB Developer Guide for more information. + /// + bool ConsistentRead { get; set; } + } + /// + /// Represents a generic interface for retrieving a batch of items + /// from a single DynamoDB table + /// + public interface IBatchGet : IBatchGet + { + /// + /// List of generic results retrieved from DynamoDB. + /// + /// + /// This is only populated after a call to Execute. + /// + List Results { get; } - #region Protected methods + /// + /// Add a single item to get, identified by its hash primary key. + /// + /// Hash key of the item to get + void AddKey(object hashKey); /// - /// Executes a server call to batch-get the items requested. - /// Populates Results with the retrieved items. + /// Add a single item to get, identified by its hash-and-range primary key. /// - internal protected abstract void ExecuteHelper(); + /// Hash key of the item to get + /// Range key of the item to get + void AddKey(object hashKey, object rangeKey); -#if AWS_ASYNC_API /// - /// Executes an asynchronous server call to batch-get the items requested. - /// Populates Results with the retrieved items. + /// Add a single item to get. /// - internal protected abstract Task ExecuteHelperAsync(CancellationToken cancellationToken); -#endif - #endregion + /// Object key of the item to get + void AddKey(T keyObject); + /// + /// Creates a MultiTableBatchGet object that is a combination + /// of the current BatchGet and the specified BatchGets + /// + /// Other BatchGet objects + /// + /// An interface with the ability to perform MultiTableBatchGet operations. + /// + IMultiTableBatchGet Combine(params IBatchGet[] otherBatches); + } - #region Internal methods + /// + /// Represents a non-generic object for retrieving a batch of items + /// from a single DynamoDB table + /// + public abstract partial class BatchGet : IBatchGet + { + internal DocumentBatchGet DocumentBatch { get; set; } internal abstract void CreateDocumentBatch(); + internal abstract void PopulateResults(List items); - #endregion + /// + public abstract int TotalKeys { get; } + + /// + public List UntypedResults { get; } = new(); + + /// + public bool ConsistentRead { get; set; } } /// /// Represents a strongly-typed object for retrieving a batch of items /// from a single DynamoDB table /// - public class BatchGet : BatchGet + public partial class BatchGet : BatchGet, IBatchGet { - #region Public properties + private readonly DynamoDBContext _context; + private readonly DynamoDBFlatConfig _config; + private readonly ItemStorageConfig _itemStorageConfig; + private readonly List _keys = new(); - /// - /// List of results retrieved from DynamoDB. - /// Populated after Execute is called. - /// - new public List Results { get { return TypedResults; } } + /// + public override int TotalKeys => _keys.Count; - #endregion + /// + public List Results { get; } = new(); - - #region Public methods - - /// - /// Add a single item to get, identified by its hash primary key. - /// - /// Hash key of the item to get + /// public void AddKey(object hashKey) { AddKey(hashKey, null); } - /// - /// Add a single item to get, identified by its hash-and-range primary key. - /// - /// Hash key of the item to get - /// Range key of the item to get + /// public void AddKey(object hashKey, object rangeKey) { - Key key = Context.MakeKey(hashKey, rangeKey, ItemStorageConfig, Config); - Keys.Add(key); + Key key = _context.MakeKey(hashKey, rangeKey, _itemStorageConfig, _config); + _keys.Add(key); } - /// - /// Add a single item to get. - /// - /// Object key of the item to get + /// public void AddKey(T keyObject) { - Key key = Context.MakeKey(keyObject, ItemStorageConfig, Config); - Keys.Add(key); + Key key = _context.MakeKey(keyObject, _itemStorageConfig, _config); + _keys.Add(key); } - /// - /// Creates a MultiTableBatchGet object that is a combination - /// of the current BatchGet and the specified BatchGets - /// - /// Other BatchGet objects - /// - /// MultiTableBatchGet consisting of the multiple BatchGet objects: - /// the current batch and the passed-in batches. - /// - public MultiTableBatchGet Combine(params BatchGet[] otherBatches) + /// + public IMultiTableBatchGet Combine(params IBatchGet[] otherBatches) { return new MultiTableBatchGet(this, otherBatches); } - #endregion - - - #region Constructor - internal BatchGet(DynamoDBContext context, DynamoDBFlatConfig config) - : base(context, config) { - ItemStorageConfig = context.StorageConfigCache.GetConfig(config); + _context = context; + _config = config; + _itemStorageConfig = context.StorageConfigCache.GetConfig(config); } - #endregion - - - #region Internal/protected/private members - - /// - /// Executes the batch get - /// - internal protected override void ExecuteHelper() + private void ExecuteHelper() { CreateDocumentBatch(); DocumentBatch.ExecuteHelper(); @@ -191,10 +177,7 @@ internal protected override void ExecuteHelper() } #if AWS_ASYNC_API - /// - /// Executes the batch get asynchronously - /// - internal protected override async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { CreateDocumentBatch(); await DocumentBatch.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); @@ -202,80 +185,78 @@ internal protected override async Task ExecuteHelperAsync(CancellationToken canc } #endif - /// - /// Gets and sets the TypedResults property. - /// - protected List TypedResults { get; set; } internal override void CreateDocumentBatch() { - var storageConfig = Context.StorageConfigCache.GetConfig(Config); - var table = Context.GetTargetTable(storageConfig, Config); + var table = _context.GetTargetTable(_itemStorageConfig, _config); DocumentBatchGet docBatch = new DocumentBatchGet(table) { - AttributesToGet = storageConfig.AttributesToGet, - ConsistentRead = this.ConsistentRead + AttributesToGet = _itemStorageConfig.AttributesToGet, + ConsistentRead = ConsistentRead }; - docBatch.Keys.AddRange(Keys); + docBatch.Keys.AddRange(_keys); DocumentBatch = docBatch; } + internal override void PopulateResults(List items) { - UntypedResults = new List(); - TypedResults = new List(); + UntypedResults.Clear(); + Results.Clear(); foreach (var doc in items) { - var item = Context.FromDocumentHelper(doc, Config); - TypedResults.Add(item); + var item = _context.FromDocumentHelper(doc, _config); + Results.Add(item); UntypedResults.Add(item); } } - - #endregion } /// - /// Class for retrieving a batch of items from multiple DynamoDB tables, + /// Interface for retrieving a batch of items from multiple DynamoDB tables, /// using multiple strongly-typed BatchGet objects /// - public partial class MultiTableBatchGet + public partial interface IMultiTableBatchGet { - #region Private members - - private List allBatches = new List(); - - #endregion + /// + /// Gets the total number of primary keys to be loaded from DynamoDB, + /// across all batches + /// + int TotalKeys { get; } + /// + /// Add a BatchGet object to the multi-table batch request + /// + /// BatchGet to add + void AddBatch(IBatchGet batch); + } - #region Constructor + /// + /// Class for retrieving a batch of items from multiple DynamoDB tables, + /// using multiple strongly-typed BatchGet objects + /// + public partial class MultiTableBatchGet : IMultiTableBatchGet + { + private List allBatches = new List(); /// /// Constructs a MultiTableBatchGet object from a number of /// BatchGet objects /// /// Collection of BatchGet objects - public MultiTableBatchGet(params BatchGet[] batches) + public MultiTableBatchGet(params IBatchGet[] batches) { - allBatches = new List(batches); + allBatches = new List(batches); } - internal MultiTableBatchGet(BatchGet first, params BatchGet[] rest) + internal MultiTableBatchGet(IBatchGet first, params IBatchGet[] rest) { - allBatches = new List(); + allBatches = new List(); allBatches.Add(first); allBatches.AddRange(rest); } - #endregion - - - #region Public properties - - /// - /// Gets the total number of primary keys to be loaded from DynamoDB, - /// across all batches - /// + /// public int TotalKeys { get @@ -283,62 +264,58 @@ public int TotalKeys int count = 0; foreach (var batch in allBatches) { - count += batch.Keys.Count; + count += batch.TotalKeys; } return count; } } - #endregion - - - #region Public methods - - /// - /// Add a BatchGet object to the multi-table batch request - /// - /// BatchGet to add - public void AddBatch(BatchGet batch) + /// + public void AddBatch(IBatchGet batch) { allBatches.Add(batch); } - internal void ExecuteHelper() + private void ExecuteHelper() { MultiTableDocumentBatchGet superBatch = new MultiTableDocumentBatchGet(); + var errorMsg = $"All batches must be of type {nameof(BatchGet)}"; foreach (var batch in allBatches) { - batch.CreateDocumentBatch(); - superBatch.AddBatch(batch.DocumentBatch); + var abstractBatch = batch as BatchGet ?? throw new InvalidOperationException(errorMsg); + abstractBatch.CreateDocumentBatch(); + superBatch.AddBatch(abstractBatch.DocumentBatch); } superBatch.ExecuteHelper(); foreach (var batch in allBatches) { - batch.PopulateResults(batch.DocumentBatch.Results); + var abstractBatch = batch as BatchGet ?? throw new InvalidOperationException(errorMsg); + abstractBatch.PopulateResults(abstractBatch.DocumentBatch.Results); } } #if AWS_ASYNC_API - internal async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { MultiTableDocumentBatchGet superBatch = new MultiTableDocumentBatchGet(); + var errorMsg = $"All batches must be of type {nameof(BatchGet)}"; foreach (var batch in allBatches) { - batch.CreateDocumentBatch(); - superBatch.AddBatch(batch.DocumentBatch); + var abstractBatch = batch as BatchGet ?? throw new InvalidOperationException(errorMsg); + abstractBatch.CreateDocumentBatch(); + superBatch.AddBatch(abstractBatch.DocumentBatch); } await superBatch.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); foreach (var batch in allBatches) { - batch.PopulateResults(batch.DocumentBatch.Results); + var abstractBatch = batch as BatchGet ?? throw new InvalidOperationException(errorMsg); + abstractBatch.PopulateResults(abstractBatch.DocumentBatch.Results); } } #endif - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 003508451426..84755c194e32 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -215,50 +215,28 @@ public void Dispose() #region BatchGet - /// - /// Creates a strongly-typed BatchGet object, allowing - /// a batch-get operation against DynamoDB. - /// - /// Type of objects to get - /// Empty strongly-typed BatchGet object - public BatchGet CreateBatchGet() + /// + public IBatchGet CreateBatchGet() { return CreateBatchGet((BatchGetConfig)null); } - /// - /// Creates a strongly-typed BatchGet object, allowing - /// a batch-get operation against DynamoDB. - /// - /// Type of objects to get - /// Config object which can be used to override that table used. - /// Empty strongly-typed BatchGet object + /// [Obsolete("Use the CreateBatchGet overload that takes BatchGetConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchGet.")] - public BatchGet CreateBatchGet(DynamoDBOperationConfig operationConfig) + public IBatchGet CreateBatchGet(DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); return new BatchGet(this, config); } - /// - /// Creates a strongly-typed BatchGet object, allowing - /// a batch-get operation against DynamoDB. - /// - /// Type of objects to get - /// Config object that can be used to override properties on the table's context for this request - /// Empty strongly-typed BatchGet object - public BatchGet CreateBatchGet(BatchGetConfig batchGetConfig) + /// + public IBatchGet CreateBatchGet(BatchGetConfig batchGetConfig) { return new BatchGet(this, new DynamoDBFlatConfig(batchGetConfig?.ToDynamoDBOperationConfig(), Config)); } - /// - /// Creates a MultiTableBatchGet object, composed of multiple - /// individual BatchGet objects. - /// - /// Individual BatchGet objects - /// Composite MultiTableBatchGet object - public MultiTableBatchGet CreateMultiTableBatchGet(params BatchGet[] batches) + /// + public IMultiTableBatchGet CreateMultiTableBatchGet(params IBatchGet[] batches) { return new MultiTableBatchGet(batches); } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index 19081d794dd5..cc8120571cd7 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -17,7 +17,6 @@ using System.Collections.Generic; using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; namespace Amazon.DynamoDBv2.DataModel { @@ -154,7 +153,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Type of objects to get /// Empty strongly-typed BatchGet object - BatchGet CreateBatchGet(); + IBatchGet CreateBatchGet(); /// /// Creates a strongly-typed BatchGet object, allowing @@ -162,9 +161,9 @@ public partial interface IDynamoDBContext : IDisposable /// /// Type of objects to get /// Config object which can be used to override that table used. - /// Empty strongly-typed BatchGet object + /// A BatchGet object using this context's configuration, which can be used to prepare and execute a BatchGet request [Obsolete("Use the CreateBatchGet overload that takes BatchGetConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchGet.")] - BatchGet CreateBatchGet(DynamoDBOperationConfig operationConfig = null); + IBatchGet CreateBatchGet(DynamoDBOperationConfig operationConfig = null); /// /// Creates a strongly-typed BatchGet object, allowing @@ -172,16 +171,16 @@ public partial interface IDynamoDBContext : IDisposable /// /// Type of objects to get /// Config object that can be used to override properties on the table's context for this request - /// Empty strongly-typed BatchGet object - public BatchGet CreateBatchGet(BatchGetConfig batchGetConfig); + /// A BatchGet object based on the provided , which can be used to prepare and execute a BatchGet request + IBatchGet CreateBatchGet(BatchGetConfig batchGetConfig); /// /// Creates a MultiTableBatchGet object, composed of multiple /// individual BatchGet objects. /// /// Individual BatchGet objects - /// Composite MultiTableBatchGet object - MultiTableBatchGet CreateMultiTableBatchGet(params BatchGet[] batches); + /// A MultiTableBatchGet object using this context's configuration, which can be used to prepare and execute a MultiTableBatchGet request + IMultiTableBatchGet CreateMultiTableBatchGet(params IBatchGet[] batches); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchGet.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchGet.Async.cs index b40710792c17..561e70161b56 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchGet.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchGet.Async.cs @@ -14,48 +14,39 @@ */ #pragma warning disable 1574 -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; -using Amazon.DynamoDBv2.DocumentModel; using System.Threading; using System.Threading.Tasks; -using Amazon.Runtime.Internal; namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for retrieving a batch of items - /// from a single DynamoDB table - /// - public abstract partial class BatchGet + public partial interface IBatchGet { - #region Public methods - /// /// Executes a server call to batch-get the items requested. /// /// 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 ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) + Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public abstract partial class BatchGet + { + /// + public abstract Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class BatchGet : BatchGet, IBatchGet + { + /// + public override Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } - /// - /// Class for retrieving a batch of items from multiple DynamoDB tables, - /// using multiple strongly-typed BatchGet objects - /// - public partial class MultiTableBatchGet + public partial interface IMultiTableBatchGet { - #region Public methods - /// /// Executes a multi-table batch request against all configured batches. /// Results are stored in the respective BatchGet objects. @@ -63,11 +54,15 @@ public partial class MultiTableBatchGet /// 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 MultiTableBatchGet : IMultiTableBatchGet + { + /// public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs index 5a320690d12c..8ca209c1a640 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -16,12 +16,9 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; -using Amazon.Runtime.Internal; namespace Amazon.DynamoDBv2.DataModel { @@ -197,31 +194,14 @@ public Task DeleteAsync(object hashKey, object rangeKey, DeleteConfig deleteC #region BatchGet async - /// - /// Issues a batch-get request with multiple batches. - /// - /// Results are stored in the individual batches. - /// - /// - /// Configured BatchGet objects - /// - public Task ExecuteBatchGetAsync(params BatchGet[] batches) + /// + public Task ExecuteBatchGetAsync(params IBatchGet[] batches) { return ExecuteBatchGetAsync(batches, default(CancellationToken)); } - /// - /// Issues a batch-get request with multiple batches. - /// - /// Results are stored in the individual batches. - /// - /// - /// Configured BatchGet objects - /// - /// - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - public Task ExecuteBatchGetAsync(BatchGet[] batches, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task ExecuteBatchGetAsync(IBatchGet[] batches, CancellationToken cancellationToken = default(CancellationToken)) { MultiTableBatchGet superBatch = new MultiTableBatchGet(batches); return superBatch.ExecuteAsync(cancellationToken); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs index 7f10ebfa10c7..1661fc68bb83 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -407,6 +407,17 @@ partial interface IDynamoDBContext #region BatchGet async + /// + /// Issues a batch-get request with multiple batches. + /// + /// Results are stored in the individual batches. + /// + /// + /// Configured BatchGet objects + /// + /// A Task that can be used to poll or wait for results, or both. + Task ExecuteBatchGetAsync(params IBatchGet[] batches); + /// /// Issues a batch-get request with multiple batches. /// @@ -417,7 +428,7 @@ partial interface IDynamoDBContext /// /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task ExecuteBatchGetAsync(BatchGet[] batches, CancellationToken cancellationToken = default(CancellationToken)); + Task ExecuteBatchGetAsync(IBatchGet[] batches, CancellationToken cancellationToken = default(CancellationToken)); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchGet.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchGet.Sync.cs index 44b0291cebdc..121e45c69fbf 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchGet.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchGet.Sync.cs @@ -13,51 +13,46 @@ * permissions and limitations under the License. */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; -using Amazon.DynamoDBv2.DocumentModel; - namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for retrieving a batch of items - /// from a single DynamoDB table - /// - public abstract partial class BatchGet + public partial interface IBatchGet { - #region Public methods - /// /// Executes a server call to batch-get the items requested. /// - public void Execute() + void Execute(); + } + + public abstract partial class BatchGet + { + /// + public abstract void Execute(); + } + + public partial class BatchGet : BatchGet, IBatchGet + { + /// + public override void Execute() { ExecuteHelper(); } - - #endregion } - /// - /// Class for retrieving a batch of items from multiple DynamoDB tables, - /// using multiple strongly-typed BatchGet objects - /// - public partial class MultiTableBatchGet + public partial interface IMultiTableBatchGet { - #region Public methods - /// /// Executes a multi-table batch request against all configured batches. /// Results are stored in the respective BatchGet objects. /// + void Execute(); + } + + public partial class MultiTableBatchGet : IMultiTableBatchGet + { + /// /> public void Execute() { ExecuteHelper(); } - - #endregion } } 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 98a57588013a..a53c03bbb1fa 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -15,10 +15,8 @@ using System; using System.Collections.Generic; -using System.Linq; using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; namespace Amazon.DynamoDBv2.DataModel { @@ -171,15 +169,8 @@ public void Delete(object hashKey, object rangeKey, DeleteConfig deleteConfig #endregion #region BatchGet - /// - /// Issues a batch-get request with multiple batches. - /// - /// Results are stored in the individual batches. - /// - /// - /// Configured BatchGet objects - /// - public void ExecuteBatchGet(params BatchGet[] batches) + /// + public void ExecuteBatchGet(params IBatchGet[] batches) { MultiTableBatchGet superBatch = new MultiTableBatchGet(batches); superBatch.Execute(); 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 504f5a2ee868..9cc39396fdf8 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -13,11 +13,9 @@ * permissions and limitations under the License. */ -using System; using System.Collections.Generic; using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; namespace Amazon.DynamoDBv2.DataModel { @@ -364,7 +362,7 @@ partial interface IDynamoDBContext /// /// Configured BatchGet objects /// - void ExecuteBatchGet(params BatchGet[] batches); + void ExecuteBatchGet(params IBatchGet[] batches); #endregion diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs new file mode 100644 index 000000000000..7d7ce4df13f1 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs @@ -0,0 +1,167 @@ +using Amazon.DynamoDBv2.DataModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; + +namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests +{ + [TestClass] + public class BatchGetTests + { + [TestMethod] + public void TestMockability_BatchGet() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateBatchGet
(It.IsAny())) + .Returns(CreateBatchGetMock(new List
() + { + { new Address() { State = "CA", Zip = "12345" }} + })); + + var ddbContext = mockContext.Object; + var addressBatchGet = ddbContext.CreateBatchGet
(); + + Assert.AreEqual(0, addressBatchGet.TotalKeys); + Assert.AreEqual(0, addressBatchGet.Results.Count); + + addressBatchGet.AddKey("CA"); + Assert.AreEqual(1, addressBatchGet.TotalKeys); + + addressBatchGet.Execute(); + Assert.AreEqual(1, addressBatchGet.Results.Count); + Assert.AreEqual("CA", addressBatchGet.Results[0].State); + Assert.AreEqual("12345", addressBatchGet.Results[0].Zip); + } + + [TestMethod] + public void TestMockability_MultiTableBatchGet() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateMultiTableBatchGet()) + .Returns(CreateMultiTableBatchGetMock()); + + var ddbContext = mockContext.Object; + var multiBatchGet = ddbContext.CreateMultiTableBatchGet(); + + var addressBatchGet = CreateBatchGetMock
(new List
+ { + { new Address() { State = "CA", Zip = "12345" }} + }); + + var personBatchGet = CreateBatchGetMock(new List + { + { new Person() { FirstName = "John", LastName = "Doe" }} + }); + + 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); + Assert.AreEqual("12345", addressBatchGet.Results[0].Zip); + Assert.AreEqual(1, personBatchGet.Results.Count); + Assert.AreEqual("John", personBatchGet.Results[0].FirstName); + Assert.AreEqual("Doe", personBatchGet.Results[0].LastName); + } + + public IBatchGet CreateBatchGetMock(List results) + { + var batchGet = new Mock>(); + var dummyResults = new List(); + var keys = new List(); + + batchGet + .Setup(x => x.Execute()) + .Callback(() => + { + dummyResults.Clear(); + dummyResults.AddRange(results); + }); + + batchGet + .Setup(x => x.Results) + .Returns(dummyResults); + + batchGet + .Setup(x => x.AddKey(It.IsAny())) + .Callback((object hashKey) => + { + keys.Add(hashKey.ToString()); + }); + + batchGet + .Setup(x => x.AddKey(It.IsAny(), It.IsAny())) + .Callback((object hashKey, object rangeKey) => + { + keys.Add(hashKey.ToString() + rangeKey.ToString()); + }); + + batchGet + .SetupGet(x => x.TotalKeys) + .Returns(() => keys.Count); + + return batchGet.Object; + } + + public IMultiTableBatchGet CreateMultiTableBatchGetMock() + { + 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((IBatchGet 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; + } + } + + public class Address + { + public string State { get; set; } + public string Zip { get; set; } + } + + public class Person + { + public string FirstName { get; set; } + public string LastName { get; set; } + } +} From 2a725efd5b863784326e76421aeb184de0d5aa03 Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Fri, 9 Aug 2024 00:26:54 -0700 Subject: [PATCH 2/7] Add the ability to mock BatchWrite and MultiTableBatchWrite operations (#3429) --- .../DynamoDBv2/Custom/DataModel/BatchWrite.cs | 270 ++++++++---------- .../DynamoDBv2/Custom/DataModel/Context.cs | 85 +----- .../Custom/DataModel/IDynamoDBContext.cs | 14 +- .../DataModel/_async/BatchWrite.Async.cs | 47 ++- .../Custom/DataModel/_async/Context.Async.cs | 12 +- .../_async/IDynamoDBContext.Async.cs | 2 +- .../Custom/DataModel/_bcl/BatchWrite.Sync.cs | 47 ++- .../Custom/DataModel/_bcl/Context.Sync.cs | 9 +- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 3 +- .../Custom/MockabilityTests/BatchGetTests.cs | 2 +- .../MockabilityTests/BatchWriteTests.cs | 121 ++++++++ 11 files changed, 313 insertions(+), 299 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs index 99958b020eb2..8c45afba89ea 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs @@ -14,10 +14,7 @@ */ using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; using Amazon.DynamoDBv2.DocumentModel; using System.Globalization; #if AWS_ASYNC_API @@ -28,56 +25,19 @@ namespace Amazon.DynamoDBv2.DataModel { /// - /// Represents a non-generic object for writing/deleting a batch of items + /// Represents a non-generic interface for writing/deleting a batch of items /// in a single DynamoDB table /// - public abstract partial class BatchWrite + public partial interface IBatchWrite { - #region Internal/protected properties - - internal DynamoDBContext Context { get; set; } - internal DynamoDBFlatConfig Config { get; set; } - internal DocumentBatchWrite DocumentBatch { get; set; } - - #endregion - - - #region Constructor - - internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config) - { - Context = context; - Config = config; - } - - #endregion - - - #region Protected methods - - /// - /// Executes a server call to batch-write/delete the items requested. - /// - internal protected abstract void ExecuteHelper(); - -#if AWS_ASYNC_API - /// - /// Executes an asynchronous server call to batch-write/delete the items requested. - /// - internal protected abstract Task ExecuteHelperAsync(CancellationToken cancellationToken); -#endif - - #endregion } /// - /// Represents a strongly-typed object for writing/deleting a batch of items + /// Represents a generic interface for writing/deleting a batch of items /// in a single DynamoDB table /// - public class BatchWrite : BatchWrite + public interface IBatchWrite : IBatchWrite { - #region Public combine methods - /// /// Creates a MultiTableBatchWrite object that is a combination /// of the current BatchWrite and the specified BatchWrites @@ -87,84 +47,38 @@ public class BatchWrite : BatchWrite /// MultiTableBatchWrite consisting of the multiple BatchWrite objects: /// the current batch and the passed-in batches. /// - public MultiTableBatchWrite Combine(params BatchWrite[] otherBatches) - { - return new MultiTableBatchWrite(this, otherBatches); - } - - #endregion - - - #region Public Put methods + IMultiTableBatchWrite Combine(params IBatchWrite[] otherBatches); /// /// Add a number of items to be put in the current batch operation /// /// Items to put - public void AddPutItems(IEnumerable values) - { - if (values == null) return; - - foreach (T item in values) - { - AddPutItem(item); - } - } + void AddPutItems(IEnumerable values); /// /// Add a single item to be put in the current batch operation /// /// - public void AddPutItem(T item) - { - if (item == null) return; - - ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: false, ignoreNullValues: true); - if (storage == null) return; - DocumentBatch.AddDocumentToPut(storage.Document); - } - - #endregion - - - #region Public Delete methods + void AddPutItem(T item); /// /// Add a number of items to be deleted in the current batch operation /// /// Items to be deleted - public void AddDeleteItems(IEnumerable values) - { - if (values == null) return; - - foreach (T item in values) - { - AddDeleteItem(item); - } - } + void AddDeleteItems(IEnumerable values); /// /// Add a single item to be deleted in the current batch operation. /// /// Item to be deleted - public void AddDeleteItem(T item) - { - if (item == null) return; - - ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: true, ignoreNullValues: true); - if (storage == null) return; - DocumentBatch.AddItemToDelete(storage.Document); - } + void AddDeleteItem(T item); /// /// Add a single item to be deleted in the current batch operation. /// Item is identified by its hash primary key. /// /// Hash key of the item to delete - public void AddDeleteKey(object hashKey) - { - AddDeleteKey(hashKey, null); - } + void AddDeleteKey(object hashKey); /// /// Add a single item to be deleted in the current batch operation. @@ -172,15 +86,27 @@ public void AddDeleteKey(object hashKey) /// /// Hash key of the item to delete /// Range key of the item to delete - public void AddDeleteKey(object hashKey, object rangeKey) - { - DocumentBatch.AddKeyToDelete(Context.MakeKey(hashKey, rangeKey, StorageConfig, Config)); - } - - #endregion + void AddDeleteKey(object hashKey, object rangeKey); + } + /// + /// Represents a non-generic object for writing/deleting a batch of items + /// in a single DynamoDB table + /// + public abstract partial class BatchWrite : IBatchWrite + { + internal DocumentBatchWrite DocumentBatch { get; set; } + } - #region Constructor + /// + /// Represents a strongly-typed object for writing/deleting a batch of items + /// in a single DynamoDB table + /// + public partial class BatchWrite : BatchWrite, IBatchWrite + { + private readonly DynamoDBContext _context; + private readonly DynamoDBFlatConfig _config; + private readonly ItemStorageConfig _storageConfig; internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config) : this(context, typeof(T), config) @@ -188,118 +114,164 @@ internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config) } internal BatchWrite(DynamoDBContext context, Type valuesType, DynamoDBFlatConfig config) - : base(context, config) { - StorageConfig = context.StorageConfigCache.GetConfig(valuesType, config); + _context = context; + _config = config; + _storageConfig = context.StorageConfigCache.GetConfig(valuesType, config); - if (StorageConfig.HasVersion) + if (_storageConfig.HasVersion) { - if (!Config.SkipVersionCheck.GetValueOrDefault(false)) + if (!_config.SkipVersionCheck.GetValueOrDefault(false)) throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Object {0} has a versioning field, which is not supported for this operation. To ignore versioning, use the DynamoDBContextConfig.SkipVersionCheck property.", valuesType.Name)); } - Table table = Context.GetTargetTable(StorageConfig, Config); + Table table = _context.GetTargetTable(_storageConfig, _config); DocumentBatch = table.CreateBatchWrite(); } - #endregion + /// + public IMultiTableBatchWrite Combine(params IBatchWrite[] otherBatches) + { + return new MultiTableBatchWrite(this, otherBatches); + } + /// + public void AddPutItems(IEnumerable values) + { + if (values == null) return; - #region Internal/protected/private members + foreach (T item in values) + { + AddPutItem(item); + } + } - internal ItemStorageConfig StorageConfig { get; set; } + /// + public void AddPutItem(T item) + { + if (item == null) return; - /// - /// Execute the batch write. - /// - internal protected override void ExecuteHelper() + ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: false, ignoreNullValues: true); + if (storage == null) return; + DocumentBatch.AddDocumentToPut(storage.Document); + } + + /// + public void AddDeleteItems(IEnumerable values) + { + if (values == null) return; + + foreach (T item in values) + { + AddDeleteItem(item); + } + } + + /// + public void AddDeleteItem(T item) + { + if (item == null) return; + + ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: true, ignoreNullValues: true); + if (storage == null) return; + DocumentBatch.AddItemToDelete(storage.Document); + } + + /// + public void AddDeleteKey(object hashKey) + { + AddDeleteKey(hashKey, null); + } + + /// + public void AddDeleteKey(object hashKey, object rangeKey) + { + DocumentBatch.AddKeyToDelete(_context.MakeKey(hashKey, rangeKey, _storageConfig, _config)); + } + + private void ExecuteHelper() { DocumentBatch.ExecuteHelper(); } #if AWS_ASYNC_API - /// - /// Execute the batch write asynchronously. - /// - internal protected override Task ExecuteHelperAsync(CancellationToken cancellationToken) + private Task ExecuteHelperAsync(CancellationToken cancellationToken) { return DocumentBatch.ExecuteHelperAsync(cancellationToken); } #endif + } - #endregion + /// + /// Interface for writing/deleting a batch of items in multiple DynamoDB tables, + /// using multiple strongly-typed BatchWrite objects + /// + public partial interface IMultiTableBatchWrite + { + /// + /// Add a BatchWrite object to the multi-table batch request + /// + /// BatchWrite to add + void AddBatch(IBatchWrite batch); } /// /// Class for writing/deleting a batch of items in multiple DynamoDB tables, /// using multiple strongly-typed BatchWrite objects /// - public partial class MultiTableBatchWrite + public partial class MultiTableBatchWrite : IMultiTableBatchWrite { - #region Private members - - private List allBatches = new List(); - - #endregion - - - #region Constructor + private List allBatches = new(); /// /// Constructs a MultiTableBatchWrite object from a number of /// BatchWrite objects /// /// Collection of BatchWrite objects - public MultiTableBatchWrite(params BatchWrite[] batches) + public MultiTableBatchWrite(params IBatchWrite[] batches) { - allBatches = new List(batches); + allBatches = new List(batches); } - internal MultiTableBatchWrite(BatchWrite first, params BatchWrite[] rest) + internal MultiTableBatchWrite(IBatchWrite first, params IBatchWrite[] rest) { - allBatches = new List(); + allBatches = new List(); allBatches.Add(first); allBatches.AddRange(rest); } - #endregion - - - #region Public methods - - /// - /// Add a BatchWrite object to the multi-table batch request - /// - /// BatchGet to add - public void AddBatch(BatchWrite batch) + /// + public void AddBatch(IBatchWrite batch) { allBatches.Add(batch); } - internal void ExecuteHelper() + private void ExecuteHelper() { MultiTableDocumentBatchWrite superBatch = new MultiTableDocumentBatchWrite(); + var errorMsg = $"All batches must be of type {nameof(BatchWrite)}"; foreach (var batch in allBatches) { - superBatch.AddBatch(batch.DocumentBatch); + var abstractBatch = batch as BatchWrite ?? throw new InvalidOperationException(errorMsg); + superBatch.AddBatch(abstractBatch.DocumentBatch); } superBatch.ExecuteHelper(); } #if AWS_ASYNC_API - internal Task ExecuteHelperAsync(CancellationToken cancellationToken) + private Task ExecuteHelperAsync(CancellationToken cancellationToken) { MultiTableDocumentBatchWrite superBatch = new MultiTableDocumentBatchWrite(); + var errorMsg = $"All batches must be of type {nameof(BatchWrite)}"; foreach (var batch in allBatches) { - superBatch.AddBatch(batch.DocumentBatch); + var abstractBatch = batch as BatchWrite ?? throw new InvalidOperationException(errorMsg); + superBatch.AddBatch(abstractBatch.DocumentBatch); } return superBatch.ExecuteHelperAsync(cancellationToken); } #endif - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 84755c194e32..38a7f3fc392f 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -245,105 +245,48 @@ public IMultiTableBatchGet CreateMultiTableBatchGet(params IBatchGet[] batches) #region BatchWrite - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// Type of objects to write - /// Empty strongly-typed BatchWrite object - public BatchWrite CreateBatchWrite() + /// + public IBatchWrite CreateBatchWrite() { return CreateBatchWrite((BatchWriteConfig)null); } - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// Type of objects to write - /// Config object which can be used to override that table used. - /// Empty strongly-typed BatchWrite object + /// [Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")] - public BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig) + public IBatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); return new BatchWrite(this, config); } - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// This is intended for use only when the valuesType is not known at compile-time, for example, - /// when hooking into EF's ChangeTracker to record audit logs from EF into DynamoDB. - /// - /// In scenarios when the valuesType is known at compile-time, the - /// method is generally preferred. - /// - /// Type of objects to write - /// Empty strongly-typed BatchWrite object - public BatchWrite CreateBatchWrite(Type valuesType) + /// + public IBatchWrite CreateBatchWrite(Type valuesType) { return CreateBatchWrite(valuesType, (BatchWriteConfig)null); } - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// This is intended for use only when the valuesType is not known at compile-time, for example, - /// when hooking into EF's ChangeTracker to record audit logs from EF into DynamoDB. - /// - /// In scenarios when the valuesType is known at compile-time, the - /// method is generally preferred. - /// - /// Type of objects to write - /// Config object which can be used to override that table used. - /// Empty strongly-typed BatchWrite object + /// [Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")] - public BatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig) + public IBatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); return new BatchWrite(this, valuesType, config); } - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// Type of objects to write - /// Config object that can be used to override properties on the table's context for this request. - /// Empty strongly-typed BatchWrite object - public BatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig) + /// + public IBatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig) { return new BatchWrite(this, new DynamoDBFlatConfig(batchWriteConfig?.ToDynamoDBOperationConfig(), Config)); } - /// - /// Creates a strongly-typed BatchWrite object, allowing - /// a batch-write operation against DynamoDB. - /// - /// This is intended for use only when the valuesType is not known at compile-time, for example, - /// when hooking into EF's ChangeTracker to record audit logs from EF into DynamoDB. - /// - /// In scenarios when the valuesType is known at compile-time, the - /// method is generally preferred. - /// - /// The type of data which will be persisted in this batch. - /// Config object that can be used to override properties on the table's context for this request. - /// Empty strongly-typed BatchWrite object - public BatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig) + /// + public IBatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig) { return new BatchWrite(this, valuesType, new DynamoDBFlatConfig(batchWriteConfig.ToDynamoDBOperationConfig(), Config)); } - /// - /// Creates a MultiTableBatchWrite object, composed of multiple - /// individual BatchWrite objects. - /// - /// Individual BatchWrite objects - /// Composite MultiTableBatchWrite object - public MultiTableBatchWrite CreateMultiTableBatchWrite(params BatchWrite[] batches) + /// + public IMultiTableBatchWrite CreateMultiTableBatchWrite(params IBatchWrite[] batches) { return new MultiTableBatchWrite(batches); } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index cc8120571cd7..d7a18828685c 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -192,7 +192,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Type of objects to write /// Empty strongly-typed BatchWrite object - BatchWrite CreateBatchWrite(); + IBatchWrite CreateBatchWrite(); /// /// Creates a strongly-typed BatchWrite object, allowing @@ -203,7 +203,7 @@ public partial interface IDynamoDBContext : IDisposable /// Empty strongly-typed BatchWrite object [Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")] - BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig = null); + IBatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig = null); /// /// Creates a strongly-typed BatchWrite object, allowing @@ -217,7 +217,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// The type of data which will be persisted in this batch. /// Empty strongly-typed BatchWrite object - BatchWrite CreateBatchWrite(Type valuesType); + IBatchWrite CreateBatchWrite(Type valuesType); /// /// Creates a strongly-typed BatchWrite object, allowing @@ -233,7 +233,7 @@ public partial interface IDynamoDBContext : IDisposable /// Config object which can be used to override that table used. /// Empty strongly-typed BatchWrite object [Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")] - BatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig = null); + IBatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig = null); /// /// Creates a strongly-typed BatchWrite object, allowing @@ -242,7 +242,7 @@ public partial interface IDynamoDBContext : IDisposable /// Type of objects to write /// Config object that can be used to override properties on the table's context for this request. /// Empty strongly-typed BatchWrite object - BatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig); + IBatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig); /// /// Creates a strongly-typed BatchWrite object, allowing @@ -257,7 +257,7 @@ public partial interface IDynamoDBContext : IDisposable /// The type of data which will be persisted in this batch. /// Config object that can be used to override properties on the table's context for this request. /// Empty strongly-typed BatchWrite object - BatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig); + IBatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig); /// /// Creates a MultiTableBatchWrite object, composed of multiple @@ -265,7 +265,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Individual BatchWrite objects /// Composite MultiTableBatchWrite object - MultiTableBatchWrite CreateMultiTableBatchWrite(params BatchWrite[] batches); + IMultiTableBatchWrite CreateMultiTableBatchWrite(params IBatchWrite[] batches); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs index 4f4cdc0d4789..ec77b8766dd5 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs @@ -14,26 +14,13 @@ */ #pragma warning disable 1574 -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; -using Amazon.DynamoDBv2.DocumentModel; using System.Threading.Tasks; -using Amazon.Runtime.Internal; using System.Threading; namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for writing/deleting a batch of items - /// in a single DynamoDB table - /// - public abstract partial class BatchWrite + public partial interface IBatchWrite { - #region Public methods - /// /// Executes a server call to batch-write/delete the items requested. /// @@ -43,22 +30,26 @@ public abstract partial class BatchWrite /// 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 ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) + Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public abstract partial class BatchWrite : IBatchWrite + { + /// + public abstract Task ExecuteAsync(CancellationToken cancellationToken); + } + + public partial class BatchWrite : BatchWrite, IBatchWrite + { + /// + public override Task ExecuteAsync(CancellationToken cancellationToken) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } - /// - /// Class for writing/deleting a batch of items in multiple DynamoDB tables, - /// using multiple strongly-typed BatchWrite objects - /// - public partial class MultiTableBatchWrite + public partial interface IMultiTableBatchWrite { - #region Public methods - /// /// Executes a multi-table batch request against all configured batches. /// @@ -68,11 +59,15 @@ public partial class MultiTableBatchWrite /// 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 MultiTableBatchWrite : IMultiTableBatchWrite + { + /// public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs index 8ca209c1a640..a408abb50e5a 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -211,16 +211,8 @@ public Task ExecuteBatchGetAsync(params IBatchGet[] batches) #region BatchWrite async - /// - /// Issues a batch-write request with multiple batches. - /// - /// - /// Configured BatchWrite objects - /// - /// - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - public Task ExecuteBatchWriteAsync(BatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task ExecuteBatchWriteAsync(IBatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken)) { MultiTableBatchWrite superBatch = new MultiTableBatchWrite(batches); return superBatch.ExecuteAsync(cancellationToken); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs index 1661fc68bb83..1417c11689c8 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -442,7 +442,7 @@ partial interface IDynamoDBContext /// /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task ExecuteBatchWriteAsync(BatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken)); + Task ExecuteBatchWriteAsync(IBatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken)); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs index e1da85c60993..68da3b2737fd 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs @@ -13,56 +13,51 @@ * permissions and limitations under the License. */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Amazon.DynamoDBv2.Model; -using Amazon.DynamoDBv2.DocumentModel; - namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for writing/deleting a batch of items - /// in a single DynamoDB table - /// - public abstract partial class BatchWrite + public partial interface IBatchWrite { - #region Public methods - /// /// Executes a server call to batch-write/delete the items requested. /// /// 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. /// - public void Execute() + void Execute(); + } + + public abstract partial class BatchWrite : IBatchWrite + { + /// + public abstract void Execute(); + } + + public partial class BatchWrite : BatchWrite, IBatchWrite + { + /// + public override void Execute() { ExecuteHelper(); } - - #endregion } - /// - /// Class for writing/deleting a batch of items in multiple DynamoDB tables, - /// using multiple strongly-typed BatchWrite objects - /// - public partial class MultiTableBatchWrite + public partial interface IMultiTableBatchWrite { - #region Public methods - /// /// Executes a multi-table batch request 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 MultiTableBatchWrite : IMultiTableBatchWrite + { + /// public void Execute() { ExecuteHelper(); } - - #endregion } } 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 a53c03bbb1fa..ea57d246b026 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -195,13 +195,8 @@ public void ExecuteTransactGet(params TransactGet[] transactionParts) #region Batch Write - /// - /// Issues a batch-write request with multiple batches. - /// - /// - /// Configured BatchWrite objects - /// - public void ExecuteBatchWrite(params BatchWrite[] batches) + /// + public void ExecuteBatchWrite(params IBatchWrite[] batches) { MultiTableBatchWrite superBatch = new MultiTableBatchWrite(batches); superBatch.Execute(); 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 9cc39396fdf8..db4c41c25729 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -13,6 +13,7 @@ * permissions and limitations under the License. */ +using System; using System.Collections.Generic; using Amazon.DynamoDBv2.DocumentModel; @@ -374,7 +375,7 @@ partial interface IDynamoDBContext /// /// Configured BatchWrite objects /// - void ExecuteBatchWrite(params BatchWrite[] batches); + void ExecuteBatchWrite(params IBatchWrite[] batches); #endregion diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs index 7d7ce4df13f1..a739c29a53fc 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs @@ -13,7 +13,7 @@ public void TestMockability_BatchGet() { var mockContext = new Mock(); mockContext - .Setup(x => x.CreateBatchGet
(It.IsAny())) + .Setup(x => x.CreateBatchGet
()) .Returns(CreateBatchGetMock(new List
() { { new Address() { State = "CA", Zip = "12345" }} diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs new file mode 100644 index 000000000000..86cd83e428be --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs @@ -0,0 +1,121 @@ +using Amazon.DynamoDBv2.DataModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; + +namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests +{ + [TestClass] + public class BatchWriteTests + { + [TestMethod] + public void TestMockability_BatchWrite() + { + var itemsToPut = new List(); + var inMemoryTable = new List(); + + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateBatchWrite()) + .Returns(CreateBatchWriteMock(itemsToPut, inMemoryTable)); + + var ddbContext = mockContext.Object; + var batchWrite = ddbContext.CreateBatchWrite(); + + Assert.AreEqual(0, inMemoryTable.Count); + Assert.AreEqual(0, itemsToPut.Count); + + batchWrite.AddPutItem("item1"); + batchWrite.AddPutItem("item2"); + Assert.AreEqual(2, itemsToPut.Count); + Assert.AreEqual(0, inMemoryTable.Count); + + batchWrite.Execute(); + Assert.AreEqual(0, itemsToPut.Count); + Assert.AreEqual(2, inMemoryTable.Count); + Assert.IsTrue(inMemoryTable.Contains("item1")); + Assert.IsTrue(inMemoryTable.Contains("item2")); + } + + [TestMethod] + public void TestMockability_MultiTableBatchWrite() + { + var itemsToPut_table1 = new List(); + var inMemory_table1 = new List(); + var batchWrite_table1 = CreateBatchWriteMock(itemsToPut_table1, inMemory_table1); + batchWrite_table1.AddPutItem("item1"); + + var itemsToPut_table2 = new List(); + var inMemory_table2 = new List(); + var batchWrite_table2 = CreateBatchWriteMock(itemsToPut_table2, inMemory_table2); + batchWrite_table2.AddPutItem("item2"); + + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateMultiTableBatchWrite()) + .Returns(CreateMultiTableBatchWriteMock()); + + var ddbContext = mockContext.Object; + var multiBatchWrite = ddbContext.CreateMultiTableBatchWrite(); + 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.IsTrue(inMemory_table1.Contains("item1")); + Assert.IsTrue(inMemory_table2.Contains("item2")); + } + + public IBatchWrite CreateBatchWriteMock(List itemsToPut, List inMemoryTable) + { + var batchWrite = new Mock>(); + + batchWrite + .Setup(x => x.AddPutItem(It.IsAny())) + .Callback((T item) => itemsToPut.Add(item)); + + batchWrite. + Setup(x => x.Execute()) + .Callback(() => + { + foreach (var item in itemsToPut) + { + inMemoryTable.Add(item); + } + + itemsToPut.Clear(); + }); + + return batchWrite.Object; + } + + public IMultiTableBatchWrite CreateMultiTableBatchWriteMock() + { + var multiBatchWrite = new Mock(); + var batches = new List(); + + multiBatchWrite + .Setup(x => x.AddBatch(It.IsAny())) + .Callback((IBatchWrite batch) => + { + batches.Add(batch); + }); + + multiBatchWrite + .Setup(x => x.Execute()) + .Callback(() => + { + foreach (var batch in batches) + { + batch.Execute(); + } + }); + + return multiBatchWrite.Object; + } + } +} From ecf850d976a2177d38110d67545a128cb8d32daa Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Tue, 13 Aug 2024 10:10:21 -0700 Subject: [PATCH 3/7] Add the ability to mock TransactGet and MultiTableTransactGet operations (#3433) --- .../DynamoDBv2/Custom/DataModel/Context.cs | 38 +-- .../Custom/DataModel/IDynamoDBContext.cs | 8 +- .../Custom/DataModel/TransactGet.cs | 263 ++++++++---------- .../Custom/DataModel/_async/Context.Async.cs | 10 +- .../_async/IDynamoDBContext.Async.cs | 2 +- .../DataModel/_async/TransactGet.Async.cs | 40 +-- .../Custom/DataModel/_bcl/Context.Sync.cs | 8 +- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 2 +- .../Custom/DataModel/_bcl/TransactGet.Sync.cs | 40 +-- .../MockabilityTests/TransactGetTests.cs | 117 ++++++++ 10 files changed, 290 insertions(+), 238 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactGetTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 38a7f3fc392f..65227512ece9 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -295,51 +295,29 @@ public IMultiTableBatchWrite CreateMultiTableBatchWrite(params IBatchWrite[] bat #region TransactGet - /// - /// Creates a strongly-typed TransactGet object, allowing - /// a transactional get operation against DynamoDB. - /// - /// Type of objects to get. - /// Empty strongly-typed TransactGet object. - public TransactGet CreateTransactGet() + /// + public ITransactGet CreateTransactGet() { return CreateTransactGet((TransactGetConfig)null); } - /// - /// Creates a strongly-typed TransactGet object, allowing - /// a transactional get operation against DynamoDB. - /// - /// Type of objects to get. - /// Config object which can be used to override that table used. - /// Empty strongly-typed TransactGet object. + /// [Obsolete("Use the CreateTransactGet overload that takes TransactGetConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchGet.")] - public TransactGet CreateTransactGet(DynamoDBOperationConfig operationConfig) + public ITransactGet CreateTransactGet(DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); return new TransactGet(this, config); } - /// - /// Creates a strongly-typed TransactGet object, allowing - /// a transactional get operation against DynamoDB. - /// - /// Type of objects to get. - /// Config object that can be used to override properties on the table's context for this request. - /// Empty strongly-typed TransactGet object. - public TransactGet CreateTransactGet(TransactGetConfig transactGetConfig) + /// + public ITransactGet CreateTransactGet(TransactGetConfig transactGetConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(transactGetConfig?.ToDynamoDBOperationConfig(), this.Config); return new TransactGet(this, config); } - /// - /// Creates a MultiTableTransactGet object, composed of multiple - /// individual TransactGet objects. - /// - /// Individual TransactGet objects. - /// Composite MultiTableTransactGet object. - public MultiTableTransactGet CreateMultiTableTransactGet(params TransactGet[] transactionParts) + /// + public IMultiTableTransactGet CreateMultiTableTransactGet(params ITransactGet[] transactionParts) { return new MultiTableTransactGet(transactionParts); } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index d7a18828685c..fc6feaaa532a 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -277,7 +277,7 @@ public partial interface IDynamoDBContext : IDisposable ///
/// Type of objects to get. /// Empty strongly-typed TransactGet object. - TransactGet CreateTransactGet(); + ITransactGet CreateTransactGet(); /// /// Creates a strongly-typed TransactGet object, allowing @@ -287,7 +287,7 @@ public partial interface IDynamoDBContext : IDisposable /// Config object which can be used to override that table used. /// Empty strongly-typed TransactGet object. [Obsolete("Use the CreateTransactGet overload that takes TransactGetConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchGet.")] - TransactGet CreateTransactGet(DynamoDBOperationConfig operationConfig = null); + ITransactGet CreateTransactGet(DynamoDBOperationConfig operationConfig = null); /// /// Creates a strongly-typed TransactGet object, allowing @@ -296,7 +296,7 @@ public partial interface IDynamoDBContext : IDisposable /// Type of objects to get. /// Config object that can be used to override properties on the table's context for this request. /// Empty strongly-typed TransactGet object. - TransactGet CreateTransactGet(TransactGetConfig transactGetConfig); + ITransactGet CreateTransactGet(TransactGetConfig transactGetConfig); /// /// Creates a MultiTableTransactGet object, composed of multiple @@ -304,7 +304,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Individual TransactGet objects. /// Composite MultiTableTransactGet object. - MultiTableTransactGet CreateMultiTableTransactGet(params TransactGet[] transactionParts); + IMultiTableTransactGet CreateMultiTableTransactGet(params ITransactGet[] transactionParts); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs index 369e6fbb54fe..a2907383a896 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGet.cs @@ -13,6 +13,7 @@ * permissions and limitations under the License. */ +using System; using System.Collections.Generic; #if AWS_ASYNC_API using System.Threading; @@ -23,124 +24,119 @@ namespace Amazon.DynamoDBv2.DataModel { /// - /// Represents a non-generic object for retrieving multiple items + /// Represents a non-generic interface for retrieving multiple items /// from a single DynamoDB table in a transaction. /// - public abstract partial class TransactGet + public partial interface ITransactGet { - #region Internal/protected properties - /// - /// Gets and sets the UntypedResults property. + /// List of non-generic results retrieved from DynamoDB. /// - protected List UntypedResults { get; set; } - internal DynamoDBContext Context { get; set; } - internal DynamoDBFlatConfig Config { get; set; } - internal DocumentTransactGet DocumentTransaction { get; set; } - - #endregion - - - #region Public properties + /// + /// This is only populated after a call to Execute. + /// + List UntypedResults { get; } + } + /// + /// Represents a generic interface for retrieving multiple items + /// from a single DynamoDB table in a transaction. + /// + public interface ITransactGet : ITransactGet + { /// - /// List of results retrieved from DynamoDB. - /// Populated after Execute is called. + /// List of generic results retrieved from DynamoDB. /// - public List Results => UntypedResults; - - #endregion - - - #region Constructor - - internal TransactGet(DynamoDBContext context, DynamoDBFlatConfig config) - { - Context = context; - Config = config; - } - - #endregion + /// + /// This is only populated after a call to Execute. + /// + List Results { get; } + /// + /// Add a single item to get, identified by its hash primary key. + /// + /// Hash key of the item to get. + void AddKey(object hashKey); - #region Protected methods + /// + /// Add a single item to get, identified by its hash-and-range primary key. + /// + /// Hash key of the item to get. + /// Range key of the item to get. + void AddKey(object hashKey, object rangeKey); /// - /// Executes a server call to get the items requested in a transaction. - /// Populates Results with the retrieved items. + /// Add a single item to get. /// - protected internal abstract void ExecuteHelper(); + /// Object key of the item to get. + void AddKey(T keyObject); -#if AWS_ASYNC_API /// - /// Executes an asynchronous server call to get the items requested in a transaction. - /// Populates Results with the retrieved items. + /// Add multiple items to get. /// - protected internal abstract Task ExecuteHelperAsync(CancellationToken cancellationToken); -#endif - #endregion + /// Object keys of the items to get. + void AddKeys(IEnumerable keyObjects); + /// + /// Creates a MultiTableTransactGet object that is a combination + /// of the current TransactGet and the specified TransactGets. + /// + /// Other TransactGet objects. + /// + /// MultiTableTransactGet consisting of the multiple TransactGet objects: + /// the current TransactGet object and the passed-in TransactGet objects. + /// + IMultiTableTransactGet Combine(params ITransactGet[] otherTransactionParts); + } - #region Internal methods + /// + /// Represents a non-generic object for retrieving multiple items + /// from a single DynamoDB table in a transaction. + /// + public abstract partial class TransactGet : ITransactGet + { + internal DocumentTransactGet DocumentTransaction { get; set; } internal abstract void PopulateResults(); - #endregion + /// + public List UntypedResults { get; } = new(); } /// /// Represents a strongly-typed object for retrieving multiple items /// from a single DynamoDB table in a transaction. /// - public class TransactGet : TransactGet + public partial class TransactGet : TransactGet, ITransactGet { - #region Public properties - - /// - /// List of results retrieved from DynamoDB. - /// Populated after Execute is called. - /// - public new List Results { get { return TypedResults; } } - - #endregion + private readonly DynamoDBContext _context; + private readonly DynamoDBFlatConfig _config; + private readonly ItemStorageConfig _storageConfig; + /// + public List Results { get; } = new(); - #region Public methods - - /// - /// Add a single item to get, identified by its hash primary key. - /// - /// Hash key of the item to get. + /// public void AddKey(object hashKey) { AddKey(hashKey, rangeKey: null); } - /// - /// Add a single item to get, identified by its hash-and-range primary key. - /// - /// Hash key of the item to get. - /// Range key of the item to get. + /// public void AddKey(object hashKey, object rangeKey) { - Key key = Context.MakeKey(hashKey, rangeKey, StorageConfig, Config); + Key key = _context.MakeKey(hashKey, rangeKey, _storageConfig, _config); DocumentTransaction.AddKeyHelper(key); } - /// - /// Add a single item to get. - /// - /// Object key of the item to get. + /// public void AddKey(T keyObject) { - Key key = Context.MakeKey(keyObject, StorageConfig, Config); + Key key = _context.MakeKey(keyObject, _storageConfig, _config); DocumentTransaction.AddKeyHelper(key); } - /// - /// Add multiple items to get. - /// - /// Object keys of the items to get. + /// public void AddKeys(IEnumerable keyObjects) { foreach (var keyObject in keyObjects) @@ -149,61 +145,29 @@ public void AddKeys(IEnumerable keyObjects) } } - /// - /// Creates a MultiTableTransactGet object that is a combination - /// of the current TransactGet and the specified TransactGets. - /// - /// Other TransactGet objects. - /// - /// MultiTableTransactGet consisting of the multiple TransactGet objects: - /// the current TransactGet object and the passed-in TransactGet objects. - /// - public MultiTableTransactGet Combine(params TransactGet[] otherTransactionParts) + /// + public IMultiTableTransactGet Combine(params ITransactGet[] otherTransactionParts) { return new MultiTableTransactGet(this, otherTransactionParts); } - #endregion - - - #region Constructor - internal TransactGet(DynamoDBContext context, DynamoDBFlatConfig config) - : base(context, config) { - StorageConfig = context.StorageConfigCache.GetConfig(config); - Table table = Context.GetTargetTable(StorageConfig, Config); + _context = context; + _config = config; + _storageConfig = context.StorageConfigCache.GetConfig(config); + var table = context.GetTargetTable(_storageConfig, config); DocumentTransaction = table.CreateTransactGet(); } - #endregion - - - #region Internal/protected/private members - - /// - /// Gets and sets the TypedResults property. - /// - protected List TypedResults { get; set; } - - internal ItemStorageConfig StorageConfig { get; set; } - - /// - /// Executes a server call to get the items requested in a transaction. - /// Populates Results with the retrieved items. - /// - protected internal override void ExecuteHelper() + private void ExecuteHelper() { DocumentTransaction.ExecuteHelper(); PopulateResults(); } #if AWS_ASYNC_API - /// - /// Executes an asynchronous server call to get the items requested in a transaction. - /// Populates Results with the retrieved items. - /// - protected internal override async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { await DocumentTransaction.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); PopulateResults(); @@ -212,96 +176,95 @@ protected internal override async Task ExecuteHelperAsync(CancellationToken canc internal override void PopulateResults() { - UntypedResults = new List(); - TypedResults = new List(); + UntypedResults.Clear(); + Results.Clear(); foreach (var doc in DocumentTransaction.Results) { - var result = Context.FromDocumentHelper(doc, Config); - TypedResults.Add(result); + var result = _context.FromDocumentHelper(doc, _config); UntypedResults.Add(result); + Results.Add(result); } } + } - #endregion + /// + /// Interface for retrieving multiple items from multiple DynamoDB tables, + /// using multiple strongly-typed TransactGet objects. + /// + public partial interface IMultiTableTransactGet + { + /// + /// Add a TransactGet object to the multi-table transaction request. + /// + /// TransactGet to add. + public void AddTransactionPart(ITransactGet transactionPart); } /// /// Class for retrieving multiple items from multiple DynamoDB tables, /// using multiple strongly-typed TransactGet objects. /// - public partial class MultiTableTransactGet + public partial class MultiTableTransactGet : IMultiTableTransactGet { - #region Private members - - private readonly List allTransactionParts; - - #endregion - - - #region Constructor + private readonly List allTransactionParts; /// /// Constructs a MultiTableTransactGet object from a number of /// TransactGet objects. /// /// Collection of TransactGet objects - public MultiTableTransactGet(params TransactGet[] transactionParts) + public MultiTableTransactGet(params ITransactGet[] transactionParts) { - allTransactionParts = new List(transactionParts); + allTransactionParts = new List(transactionParts); } - internal MultiTableTransactGet(TransactGet first, params TransactGet[] rest) + internal MultiTableTransactGet(ITransactGet first, params ITransactGet[] rest) { - allTransactionParts = new List(); + allTransactionParts = new List(); allTransactionParts.Add(first); allTransactionParts.AddRange(rest); } - #endregion - - - #region Public methods - - /// - /// Add a TransactGet object to the multi-table transaction request. - /// - /// TransactGet to add. - public void AddTransactionPart(TransactGet transactionPart) + /// + public void AddTransactionPart(ITransactGet transactionPart) { allTransactionParts.Add(transactionPart); } - - internal void ExecuteHelper() + private void ExecuteHelper() { MultiTableDocumentTransactGet transaction = new MultiTableDocumentTransactGet(); + var errorMsg = $"All transactionParts must be of type {nameof(TransactGet)}"; foreach (var transactionPart in allTransactionParts) { - transaction.AddTransactionPart(transactionPart.DocumentTransaction); + var abstractTransactGet = transactionPart as TransactGet ?? throw new InvalidOperationException(errorMsg); + transaction.AddTransactionPart(abstractTransactGet.DocumentTransaction); } transaction.ExecuteHelper(); foreach (var transactionPart in allTransactionParts) { - transactionPart.PopulateResults(); + var abstractTransactGet = transactionPart as TransactGet ?? throw new InvalidOperationException(errorMsg); + abstractTransactGet.PopulateResults(); } } #if AWS_ASYNC_API - internal async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { MultiTableDocumentTransactGet transaction = new MultiTableDocumentTransactGet(); + var errorMsg = $"All transactionParts must be of type {nameof(TransactGet)}"; foreach (var transactionPart in allTransactionParts) { - transaction.AddTransactionPart(transactionPart.DocumentTransaction); + var abstractTransactGet = transactionPart as TransactGet ?? throw new InvalidOperationException(errorMsg); + transaction.AddTransactionPart(abstractTransactGet.DocumentTransaction); } await transaction.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); foreach (var transactionPart in allTransactionParts) { - transactionPart.PopulateResults(); + var abstractTransactGet = transactionPart as TransactGet ?? throw new InvalidOperationException(errorMsg); + abstractTransactGet.PopulateResults(); } } #endif - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs index a408abb50e5a..ea988db96666 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -222,14 +222,8 @@ public Task ExecuteBatchGetAsync(params IBatchGet[] batches) #region TransactGet async - /// - /// Issues a transactional get request with multiple TransactGet objects. - /// Results are stored in the individual TransactGet objects. - /// - /// Configured TransactGet objects. - /// 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 ExecuteTransactGetAsync(TransactGet[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task ExecuteTransactGetAsync(ITransactGet[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)) { MultiTableTransactGet transaction = new MultiTableTransactGet(transactionParts); return transaction.ExecuteAsync(cancellationToken); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs index 1417c11689c8..267f226345d0 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -455,7 +455,7 @@ partial interface IDynamoDBContext /// Configured TransactGet 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 ExecuteTransactGetAsync(TransactGet[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)); + Task ExecuteTransactGetAsync(ITransactGet[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactGet.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactGet.Async.cs index d56455103b06..e970efd3e38b 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactGet.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactGet.Async.cs @@ -18,35 +18,33 @@ namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for retrieving multiple items - /// from a single DynamoDB table in a transaction. - /// - public abstract partial class TransactGet + public partial interface ITransactGet { - #region Public methods - /// /// Executes a server call to get the items requested 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. - public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) + Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public abstract partial class TransactGet : ITransactGet + { + /// + public abstract Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class TransactGet : TransactGet, ITransactGet + { + /// + public override Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } - /// - /// Class for retrieving multiple items from multiple DynamoDB tables, - /// using multiple strongly-typed TransactGet objects. - /// - public partial class MultiTableTransactGet + public partial interface IMultiTableTransactGet { - #region Public methods - /// /// Executes a multi-table transaction request against all configured TransactGet objects. /// Results are stored in the respective TransactGet objects. @@ -54,11 +52,15 @@ public partial class MultiTableTransactGet /// 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 ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class MultiTableTransactGet : IMultiTableTransactGet + { + /// public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } } 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 ea57d246b026..21cff9c72e95 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -180,12 +180,8 @@ public void ExecuteBatchGet(params IBatchGet[] batches) #region Transact Get - /// - /// Issues a transactional get request with multiple TransactGet objects. - /// Results are stored in the individual TransactGet objects. - /// - /// Configured TransactGet objects. - public void ExecuteTransactGet(params TransactGet[] transactionParts) + /// + public void ExecuteTransactGet(params ITransactGet[] transactionParts) { MultiTableTransactGet transaction = new MultiTableTransactGet(transactionParts); transaction.Execute(); 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 db4c41c25729..1655c635d095 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -386,7 +386,7 @@ partial interface IDynamoDBContext /// Results are stored in the individual TransactGet objects. /// /// Configured TransactGet objects. - void ExecuteTransactGet(params TransactGet[] transactionParts); + void ExecuteTransactGet(params ITransactGet[] transactionParts); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactGet.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactGet.Sync.cs index 4427246c9896..a964b8f79c24 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactGet.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactGet.Sync.cs @@ -15,42 +15,44 @@ namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for retrieving multiple items - /// from a single DynamoDB table in a transaction. - /// - public partial class TransactGet + public partial interface ITransactGet { - #region Public methods - /// /// Executes a server call to get the items requested in a transaction. /// - public void Execute() + void Execute(); + } + + public partial class TransactGet : ITransactGet + { + /// + public abstract void Execute(); + } + + public partial class TransactGet : TransactGet, ITransactGet + { + /// + public override void Execute() { ExecuteHelper(); } - - #endregion } - /// - /// Class for retrieving multiple items from multiple DynamoDB tables, - /// using multiple strongly-typed TransactGet objects. - /// - public partial class MultiTableTransactGet + public partial interface IMultiTableTransactGet { - #region Public methods - /// /// Executes a multi-table transaction request against all configured TransactGet objects. /// Results are stored in the respective TransactGet objects. /// + void Execute(); + } + + public partial class MultiTableTransactGet + { + /// public void Execute() { ExecuteHelper(); } - - #endregion } } diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactGetTests.cs new file mode 100644 index 000000000000..1446e54bfbdf --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactGetTests.cs @@ -0,0 +1,117 @@ +using Amazon.DynamoDBv2.DataModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; + +namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests +{ + [TestClass] + public class TransactGetTests + { + [TestMethod] + public void TestMockability_TransactGet() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateTransactGet
()) + .Returns(CreateTransactGetMock(new List
() + { + { new Address() { State = "CA", Zip = "12345" }} + })); + + var ddbContext = mockContext.Object; + var addressTransactGet = ddbContext.CreateTransactGet
(); + + + Assert.AreEqual(0, addressTransactGet.Results.Count); + + addressTransactGet.Execute(); + Assert.AreEqual(1, addressTransactGet.Results.Count); + Assert.AreEqual("CA", addressTransactGet.Results[0].State); + Assert.AreEqual("12345", addressTransactGet.Results[0].Zip); + } + + [TestMethod] + public void TestMockability_MultiTableTransactGet() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateMultiTableTransactGet()) + .Returns(CreateMultiTableTransactGetMock()); + + var ddbContext = mockContext.Object; + var multiTransactGet = ddbContext.CreateMultiTableTransactGet(); + + var addressTransactGet = CreateTransactGetMock(new List
+ { + { new Address() { State = "CA", Zip = "12345" }} + }); + + var personTransactGet = CreateTransactGetMock(new List + { + { new Person() { FirstName = "John", LastName = "Doe" }} + }); + + 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); + Assert.AreEqual("12345", addressTransactGet.Results[0].Zip); + Assert.AreEqual(1, personTransactGet.Results.Count); + Assert.AreEqual("John", personTransactGet.Results[0].FirstName); + Assert.AreEqual("Doe", personTransactGet.Results[0].LastName); + } + + public ITransactGet CreateTransactGetMock(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 IMultiTableTransactGet CreateMultiTableTransactGetMock() + { + 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((ITransactGet batch) => + { + batches.Add(batch); + }); + + return multiTransactGet.Object; + } + } +} From ea25913e3c142ae16bfbf31feebcc7baefa49a01 Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Wed, 21 Aug 2024 10:00:36 -0700 Subject: [PATCH 4/7] Add the ability to mock TransactWrite and MultiTableTransactWrite operations (#3436) --- .../DynamoDBv2/Custom/DataModel/Context.cs | 38 +- .../Custom/DataModel/IDynamoDBContext.cs | 8 +- .../Custom/DataModel/TransactWrite.cs | 406 +++++++++--------- .../Custom/DataModel/_async/Context.Async.cs | 9 +- .../_async/IDynamoDBContext.Async.cs | 2 +- .../DataModel/_async/TransactWrite.Async.cs | 40 +- .../Custom/DataModel/_bcl/Context.Sync.cs | 7 +- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 2 +- .../DataModel/_bcl/TransactWrite.Sync.cs | 40 +- .../MockabilityTests/TransactWriteTests.cs | 121 ++++++ 10 files changed, 380 insertions(+), 293 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactWriteTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 65227512ece9..845b2a9cdd13 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -326,52 +326,30 @@ public IMultiTableTransactGet CreateMultiTableTransactGet(params ITransactGet[] #region TransactWrite - /// - /// Creates a strongly-typed TransactWrite object, allowing - /// a transactional write operation against DynamoDB. - /// - /// Type of objects to write. - /// Empty strongly-typed TransactWrite object. - public TransactWrite CreateTransactWrite() + /// + public ITransactWrite CreateTransactWrite() { return CreateTransactWrite((TransactWriteConfig)null); } - /// - /// Creates a strongly-typed TransactWrite object, allowing - /// a transactional write operation against DynamoDB. - /// - /// Type of objects to write. - /// Config object which can be used to override that table used. - /// Empty strongly-typed TransactWrite object. + /// [Obsolete("Use the CreateTransactWrite overload that takes TransactWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to CreateTransactWrite.")] - public TransactWrite CreateTransactWrite(DynamoDBOperationConfig operationConfig) + public ITransactWrite CreateTransactWrite(DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); return new TransactWrite(this, config); } - /// - /// Creates a strongly-typed TransactWrite object, allowing - /// a transactional write operation against DynamoDB. - /// - /// Type of objects to write. - /// Config object that can be used to override properties on the table's context for this request. - /// Empty strongly-typed TransactWrite object. - public TransactWrite CreateTransactWrite(TransactWriteConfig transactWriteConfig) + /// + public ITransactWrite CreateTransactWrite(TransactWriteConfig transactWriteConfig) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(transactWriteConfig?.ToDynamoDBOperationConfig(), this.Config); return new TransactWrite(this, config); } - /// - /// Creates a MultiTableTransactWrite object, composed of multiple - /// individual TransactWrite objects. - /// - /// Individual TransactWrite objects. - /// Composite MultiTableTransactWrite object. - public MultiTableTransactWrite CreateMultiTableTransactWrite(params TransactWrite[] transactionParts) + /// + public IMultiTableTransactWrite CreateMultiTableTransactWrite(params ITransactWrite[] transactionParts) { return new MultiTableTransactWrite(transactionParts); } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index fc6feaaa532a..c9941d2bc5b4 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -316,7 +316,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Type of objects to write. /// Empty strongly-typed TransactWrite object. - TransactWrite CreateTransactWrite(); + ITransactWrite CreateTransactWrite(); /// /// Creates a strongly-typed TransactWrite object, allowing @@ -326,7 +326,7 @@ public partial interface IDynamoDBContext : IDisposable /// Config object which can be used to override that table used. /// Empty strongly-typed TransactWrite object. [Obsolete("Use the CreateTransactWrite overload that takes TransactWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to CreateTransactWrite.")] - TransactWrite CreateTransactWrite(DynamoDBOperationConfig operationConfig = null); + ITransactWrite CreateTransactWrite(DynamoDBOperationConfig operationConfig = null); /// /// Creates a strongly-typed TransactWrite object, allowing @@ -335,7 +335,7 @@ public partial interface IDynamoDBContext : IDisposable /// Type of objects to write. /// Config object that can be used to override properties on the table's context for this request. /// Empty strongly-typed TransactWrite object. - TransactWrite CreateTransactWrite(TransactWriteConfig transactWriteConfig); + ITransactWrite CreateTransactWrite(TransactWriteConfig transactWriteConfig); /// /// Creates a MultiTableTransactWrite object, composed of multiple @@ -343,7 +343,7 @@ public partial interface IDynamoDBContext : IDisposable /// /// Individual TransactWrite objects. /// Composite MultiTableTransactWrite object. - MultiTableTransactWrite CreateMultiTableTransactWrite(params TransactWrite[] transactionParts); + IMultiTableTransactWrite CreateMultiTableTransactWrite(params ITransactWrite[] transactionParts); #endregion } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs index 5aa70cea7464..42ff4668e246 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWrite.cs @@ -24,53 +24,148 @@ namespace Amazon.DynamoDBv2.DataModel { + /// - /// Represents a non-generic object for writing/deleting/version-checking multiple items + /// Represents a non-generic interface for writing/deleting/version-checking multiple items /// in a single DynamoDB table in a transaction. /// - public abstract partial class TransactWrite + public partial interface ITransactWrite { - #region Internal/protected properties + } - internal DynamoDBContext Context { get; set; } - internal DynamoDBFlatConfig Config { get; set; } - internal DocumentTransactWrite DocumentTransaction { get; set; } + /// + /// Represents a generic interface for writing/deleting/version-checking multiple items + /// in a single DynamoDB table in a transaction. + /// + public interface ITransactWrite : ITransactWrite + { + /// + /// Creates a MultiTableTransactWrite object that is a combination + /// of the current TransactWrite and the specified TransactWrites. + /// + /// Other TransactWrite objects. + /// + /// MultiTableTransactWrite consisting of the multiple TransactWrite objects: + /// the current TransactWrite object and the passed-in TransactWrite objects. + /// + MultiTableTransactWrite Combine(params TransactWrite[] otherTransactionParts); - #endregion + /// + /// Add a number of items to be saved in the current transaction operation. + /// + /// Items to save. + void AddSaveItems(IEnumerable values); + /// + /// Add a single item to be saved in the current transaction operation. + /// + /// Item to save. + void AddSaveItem(T item); - #region Constructor + /// + /// Add a single item to be saved in the current transaction operation. + /// Item is identified by its hash primary key and will be updated using the update expression provided. + /// + /// Hash key of the item to delete. + /// Update expression to use. + /// Condition to check before the operation. + void AddSaveItem(object hashKey, Expression updateExpression, Expression conditionExpression = null); - internal TransactWrite(DynamoDBContext context, DynamoDBFlatConfig config) - { - Context = context; - Config = config; - } + /// + /// Add a single item to be saved in the current transaction operation. + /// Item is identified by its hash-and-range primary key and will be updated using the update expression provided. + /// + /// Hash key of the item to delete. + /// Range key of the item to delete. + /// Update expression to use. + /// Condition to check before the operation. + void AddSaveItem(object hashKey, object rangeKey, Expression updateExpression, Expression conditionExpression = null); - #endregion + /// + /// Add a number of items to be deleted in the current transaction operation. + /// + /// Items to be deleted. + void AddDeleteItems(IEnumerable values); + /// + /// Add a single item to be deleted in the current transaction operation. + /// + /// Item to be deleted. + void AddDeleteItem(T item); - #region Protected methods + /// + /// Add a single item to be deleted in the current transaction operation. + /// Item is identified by its hash primary key. + /// + /// Hash key of the item to delete. + void AddDeleteKey(object hashKey); /// - /// Executes a server call to write/delete/version-check the items requested in a transaction. + /// Add a single item to be deleted in the current transaction operation. + /// Item is identified by its hash primary key. /// - protected internal abstract void ExecuteHelper(); + /// Hash key of the item to delete. + /// Condition to check before the operation. + void AddDeleteKey(object hashKey, Expression conditionExpression); + + /// + /// Add a single item to be deleted in the current transaction operation. + /// Item is identified by its hash-and-range primary key. + /// + /// Hash key of the item to delete. + /// Range key of the item to delete. + void AddDeleteKey(object hashKey, object rangeKey); -#if AWS_ASYNC_API /// - /// Executes an asynchronous server call to write/delete/version-check the items requested in a transaction. + /// Add a single item to be deleted in the current transaction operation. + /// Item is identified by its hash-and-range primary key. /// - protected internal abstract Task ExecuteHelperAsync(CancellationToken cancellationToken); -#endif - #endregion + /// Hash key of the item to delete. + /// Range key of the item to delete. + /// Condition to check before the operation. + void AddDeleteKey(object hashKey, object rangeKey, Expression conditionExpression); + /// + /// Add a single item to be version checked in the current transaction operation. + /// The item must have a single property marked with the DynamoDBVersionAttribute. + /// + /// Item to be version checked. + void AddVersionCheckItem(T item); - #region Internal methods + /// + /// Add a number of items to be version checked in the current transaction operation. + /// All items must have a single property marked with the DynamoDBVersionAttribute. + /// + /// Items to be version checked. + void AddVersionCheckItems(IEnumerable items); - internal abstract void PopulateObjects(); + /// + /// Add a single item to be version checked in the current transaction operation. + /// Item is identified by its hash primary key. + /// + /// Hash key of the item to be version checked. + /// Version of the item. + void AddVersionCheckKey(object hashKey, object version); + + /// + /// Add a single item to be version checked in the current transaction operation. + /// Item is identified by its hash-and-range primary key. + /// + /// Hash key of the item to be version checked. + /// Range key of the item to be version checked. + /// Version of the item. + void AddVersionCheckKey(object hashKey, object rangeKey, object version); + } + + /// + /// Represents a non-generic object for writing/deleting/version-checking multiple items + /// in a single DynamoDB table in a transaction. + /// + public abstract partial class TransactWrite : ITransactWrite + { + internal DocumentTransactWrite DocumentTransaction { get; set; } - #endregion + internal abstract void PopulateObjects(); } /// @@ -80,33 +175,29 @@ internal TransactWrite(DynamoDBContext context, DynamoDBFlatConfig config) #if NET8_0_OR_GREATER [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] #endif - public class TransactWrite : TransactWrite + public partial class TransactWrite : TransactWrite, ITransactWrite { - #region Public Combine methods + private readonly DynamoDBContext _context; + private readonly DynamoDBFlatConfig _config; + private readonly ItemStorageConfig _storageConfig; + private readonly List _objectItems = new(); - /// - /// Creates a MultiTableTransactWrite object that is a combination - /// of the current TransactWrite and the specified TransactWrites. - /// - /// Other TransactWrite objects. - /// - /// MultiTableTransactWrite consisting of the multiple TransactWrite objects: - /// the current TransactWrite object and the passed-in TransactWrite objects. - /// + internal TransactWrite(DynamoDBContext context, DynamoDBFlatConfig config) + { + _context = context; + _config = config; + _storageConfig = context.StorageConfigCache.GetConfig(config); + Table table = _context.GetTargetTable(_storageConfig, _config); + DocumentTransaction = table.CreateTransactWrite(); + } + + /// public MultiTableTransactWrite Combine(params TransactWrite[] otherTransactionParts) { return new MultiTableTransactWrite(this, otherTransactionParts); } - #endregion - - - #region Public Save methods - - /// - /// Add a number of items to be saved in the current transaction operation. - /// - /// Items to save. + /// public void AddSaveItems(IEnumerable values) { if (values == null) return; @@ -117,15 +208,12 @@ public void AddSaveItems(IEnumerable values) } } - /// - /// Add a single item to be saved in the current transaction operation. - /// - /// Item to save. + /// public void AddSaveItem(T item) { if (item == null) return; - ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: false, Config.IgnoreNullValues ?? false); + ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: false, _config.IgnoreNullValues ?? false); if (storage == null) return; Expression conditionExpression = CreateConditionExpressionForVersion(storage); SetNewVersion(storage); @@ -140,29 +228,16 @@ public void AddSaveItem(T item) OriginalObject = item, ItemStorage = storage }; - objectItems.Add(objectItem); + _objectItems.Add(objectItem); } - /// - /// Add a single item to be saved in the current transaction operation. - /// Item is identified by its hash primary key and will be updated using the update expression provided. - /// - /// Hash key of the item to delete. - /// Update expression to use. - /// Condition to check before the operation. + /// public void AddSaveItem(object hashKey, Expression updateExpression, Expression conditionExpression = null) { AddSaveItem(hashKey, rangeKey: null, updateExpression, conditionExpression); } - /// - /// Add a single item to be saved in the current transaction operation. - /// Item is identified by its hash-and-range primary key and will be updated using the update expression provided. - /// - /// Hash key of the item to delete. - /// Range key of the item to delete. - /// Update expression to use. - /// Condition to check before the operation. + /// public void AddSaveItem(object hashKey, object rangeKey, Expression updateExpression, Expression conditionExpression = null) { var operationConfig = conditionExpression != null @@ -173,18 +248,10 @@ public void AddSaveItem(object hashKey, object rangeKey, Expression updateExpres } : null; - DocumentTransaction.AddDocumentToUpdateHelper(Context.MakeKey(hashKey, rangeKey, StorageConfig, Config), updateExpression, operationConfig); + DocumentTransaction.AddDocumentToUpdateHelper(_context.MakeKey(hashKey, rangeKey, _storageConfig, _config), updateExpression, operationConfig); } - #endregion - - - #region Public Delete methods - - /// - /// Add a number of items to be deleted in the current transaction operation. - /// - /// Items to be deleted. + /// public void AddDeleteItems(IEnumerable values) { if (values == null) return; @@ -195,15 +262,12 @@ public void AddDeleteItems(IEnumerable values) } } - /// - /// Add a single item to be deleted in the current transaction operation. - /// - /// Item to be deleted. + /// public void AddDeleteItem(T item) { if (item == null) return; - ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: true, Config.IgnoreNullValues ?? false); + ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: true, _config.IgnoreNullValues ?? false); if (storage == null) return; Expression conditionExpression = CreateConditionExpressionForVersion(storage); @@ -214,45 +278,25 @@ public void AddDeleteItem(T item) }); } - /// - /// Add a single item to be deleted in the current transaction operation. - /// Item is identified by its hash primary key. - /// - /// Hash key of the item to delete. + /// public void AddDeleteKey(object hashKey) { AddDeleteKey(hashKey, conditionExpression: null); } - /// - /// Add a single item to be deleted in the current transaction operation. - /// Item is identified by its hash primary key. - /// - /// Hash key of the item to delete. - /// Condition to check before the operation. + /// public void AddDeleteKey(object hashKey, Expression conditionExpression) { AddDeleteKey(hashKey, rangeKey: null, conditionExpression); } - /// - /// Add a single item to be deleted in the current transaction operation. - /// Item is identified by its hash-and-range primary key. - /// - /// Hash key of the item to delete. - /// Range key of the item to delete. + /// public void AddDeleteKey(object hashKey, object rangeKey) { AddDeleteKey(hashKey, rangeKey, conditionExpression: null); } - /// - /// Add a single item to be deleted in the current transaction operation. - /// Item is identified by its hash-and-range primary key. - /// - /// Hash key of the item to delete. - /// Range key of the item to delete. - /// Condition to check before the operation. + /// public void AddDeleteKey(object hashKey, object rangeKey, Expression conditionExpression) { var operationConfig = conditionExpression != null @@ -263,26 +307,17 @@ public void AddDeleteKey(object hashKey, object rangeKey, Expression conditionEx } : null; - DocumentTransaction.AddKeyToDeleteHelper(Context.MakeKey(hashKey, rangeKey, StorageConfig, Config), operationConfig); + DocumentTransaction.AddKeyToDeleteHelper(_context.MakeKey(hashKey, rangeKey, _storageConfig, _config), operationConfig); } - #endregion - - - #region Public VersionCheck methods - - /// - /// Add a single item to be version checked in the current transaction operation. - /// The item must have a single property marked with the DynamoDBVersionAttribute. - /// - /// Item to be version checked. + /// public void AddVersionCheckItem(T item) { CheckUseVersioning(); if (item == null) return; - ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: true, Config.IgnoreNullValues ?? false); + ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: true, _config.IgnoreNullValues ?? false); if (storage == null) return; Expression conditionExpression = CreateConditionExpressionForVersion(storage); @@ -293,11 +328,7 @@ public void AddVersionCheckItem(T item) }); } - /// - /// Add a number of items to be version checked in the current transaction operation. - /// All items must have a single property marked with the DynamoDBVersionAttribute. - /// - /// Items to be version checked. + /// public void AddVersionCheckItems(IEnumerable items) { foreach (var item in items) @@ -306,40 +337,29 @@ public void AddVersionCheckItems(IEnumerable items) } } - /// - /// Add a single item to be version checked in the current transaction operation. - /// Item is identified by its hash primary key. - /// - /// Hash key of the item to be version checked. - /// Version of the item. + /// public void AddVersionCheckKey(object hashKey, object version) { AddVersionCheckKey(hashKey, rangeKey: null, version); } - /// - /// Add a single item to be version checked in the current transaction operation. - /// Item is identified by its hash-and-range primary key. - /// - /// Hash key of the item to be version checked. - /// Range key of the item to be version checked. - /// Version of the item. + /// public void AddVersionCheckKey(object hashKey, object rangeKey, object version) { CheckUseVersioning(); - Key key = Context.MakeKey(hashKey, rangeKey, StorageConfig, Config); - DynamoDBEntry versionEntry = Context.ToDynamoDBEntry(StorageConfig.VersionPropertyStorage, version, Config); + Key key = _context.MakeKey(hashKey, rangeKey, _storageConfig, _config); + DynamoDBEntry versionEntry = _context.ToDynamoDBEntry(_storageConfig.VersionPropertyStorage, version, _config); Primitive versionPrimitive = versionEntry?.AsPrimitive(); if (versionEntry != null && versionPrimitive == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Version property {0} must be Primitive.", - StorageConfig.VersionPropertyName)); + _storageConfig.VersionPropertyName)); } - ItemStorage storage = new ItemStorage(StorageConfig) + ItemStorage storage = new ItemStorage(_storageConfig) { CurrentVersion = versionPrimitive }; @@ -353,42 +373,14 @@ public void AddVersionCheckKey(object hashKey, object rangeKey, object version) }); } - #endregion - - - #region Constructor - - internal TransactWrite(DynamoDBContext context, DynamoDBFlatConfig config) - : base(context, config) - { - StorageConfig = context.StorageConfigCache.GetConfig(config); - Table table = Context.GetTargetTable(StorageConfig, Config); - DocumentTransaction = table.CreateTransactWrite(); - } - - #endregion - - - #region Internal/protected/private members - - private readonly List objectItems = new List(); - - internal ItemStorageConfig StorageConfig { get; set; } - - /// - /// Executes a server call to write/delete/version-check the items requested in a transaction. - /// - protected internal override void ExecuteHelper() + private void ExecuteHelper() { DocumentTransaction.ExecuteHelper(); PopulateObjects(); } #if AWS_ASYNC_API - /// - /// Executes an asynchronous server call to write/delete/version-check the items requested in a transaction. - /// - protected internal override async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { await DocumentTransaction.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); PopulateObjects(); @@ -397,27 +389,27 @@ protected internal override async Task ExecuteHelperAsync(CancellationToken canc internal override void PopulateObjects() { - foreach (var objectItem in objectItems) + foreach (var objectItem in _objectItems) { - objectItem.PopulateObject(Context, Config); + objectItem.PopulateObject(_context, _config); } } private bool ShouldUseVersioning() { - var skipVersionCheck = Config.SkipVersionCheck ?? false; - return !skipVersionCheck && StorageConfig.HasVersion; + var skipVersionCheck = _config.SkipVersionCheck ?? false; + return !skipVersionCheck && _storageConfig.HasVersion; } private void CheckUseVersioning() { - if (Config.SkipVersionCheck == true) + if (_config.SkipVersionCheck == true) { throw new InvalidOperationException( "Using DynamoDBContextConfig.SkipVersionCheck property with true value is not supported for this operation."); } - if (!StorageConfig.HasVersion) + if (!_storageConfig.HasVersion) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Object {0} does not have a versioning field, which is not supported for this operation.", @@ -439,86 +431,86 @@ private void SetNewVersion(ItemStorage storage) if (!ShouldUseVersioning()) return; DynamoDBContext.SetNewVersion(storage); } + } - #endregion + /// + /// Interface for writing/deleting/version-checking multiple items in multiple DynamoDB tables, + /// using multiple strongly-typed TransactWrite objects. + /// + public partial interface IMultiTableTransactWrite + { + /// + /// Add a TransactWrite object to the multi-table transaction request. + /// + /// TransactWrite to add. + void AddTransactionPart(ITransactWrite transactionPart); } /// /// Class for writing/deleting/version-checking multiple items in multiple DynamoDB tables, /// using multiple strongly-typed TransactWrite objects. /// - public partial class MultiTableTransactWrite + public partial class MultiTableTransactWrite : IMultiTableTransactWrite { - #region Private members - - private readonly List allTransactionParts; - - #endregion - - - #region Constructor + private readonly List allTransactionParts; /// /// Constructs a MultiTableTransactWrite object from a number of /// TransactWrite objects /// /// Collection of TransactWrite objects - public MultiTableTransactWrite(params TransactWrite[] transactionParts) + public MultiTableTransactWrite(params ITransactWrite[] transactionParts) { - allTransactionParts = new List(transactionParts); + allTransactionParts = new List(transactionParts); } - internal MultiTableTransactWrite(TransactWrite first, params TransactWrite[] rest) + internal MultiTableTransactWrite(ITransactWrite first, params ITransactWrite[] rest) { - allTransactionParts = new List(); + allTransactionParts = new List(); allTransactionParts.Add(first); allTransactionParts.AddRange(rest); } - #endregion - - - #region Public methods - - /// - /// Add a TransactWrite object to the multi-table transaction request. - /// - /// TransactWrite to add. - public void AddTransactionPart(TransactWrite transactionPart) + /// + public void AddTransactionPart(ITransactWrite transactionPart) { allTransactionParts.Add(transactionPart); } - internal void ExecuteHelper() + private void ExecuteHelper() { MultiTableDocumentTransactWrite transaction = new MultiTableDocumentTransactWrite(); + var errMsg = $"All transactionParts must be of type {nameof(TransactWrite)}"; foreach (var transactionPart in allTransactionParts) { - transaction.AddTransactionPart(transactionPart.DocumentTransaction); + var abstractTransactWrite = transactionPart as TransactWrite ?? throw new InvalidOperationException(errMsg); + transaction.AddTransactionPart(abstractTransactWrite.DocumentTransaction); } transaction.ExecuteHelper(); foreach (var transactionPart in allTransactionParts) { - transactionPart.PopulateObjects(); + var abstractTransactWrite = transactionPart as TransactWrite ?? throw new InvalidOperationException(errMsg); + abstractTransactWrite.PopulateObjects(); } } #if AWS_ASYNC_API - internal async Task ExecuteHelperAsync(CancellationToken cancellationToken) + private async Task ExecuteHelperAsync(CancellationToken cancellationToken) { MultiTableDocumentTransactWrite transaction = new MultiTableDocumentTransactWrite(); + var errMsg = $"All transactionParts must be of type {nameof(TransactWrite)}"; foreach (var transactionPart in allTransactionParts) { - transaction.AddTransactionPart(transactionPart.DocumentTransaction); + var abstractTransactWrite = transactionPart as TransactWrite ?? throw new InvalidOperationException(errMsg); + transaction.AddTransactionPart(abstractTransactWrite.DocumentTransaction); } await transaction.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false); foreach (var transactionPart in allTransactionParts) { - transactionPart.PopulateObjects(); + var abstractTransactWrite = transactionPart as TransactWrite ?? throw new InvalidOperationException(errMsg); + abstractTransactWrite.PopulateObjects(); } } #endif - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs index ea988db96666..6d5ca468ebf3 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -233,13 +233,8 @@ public Task ExecuteBatchGetAsync(params IBatchGet[] batches) #region TransactWrite async - /// - /// Issues a transactional write request with multiple TransactWrite objects. - /// - /// Configured TransactWrite objects. - /// 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 ExecuteTransactWriteAsync(TransactWrite[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task ExecuteTransactWriteAsync(ITransactWrite[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)) { MultiTableTransactWrite transaction = new MultiTableTransactWrite(transactionParts); return transaction.ExecuteAsync(cancellationToken); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs index 267f226345d0..848d12b8aa69 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -467,7 +467,7 @@ partial interface IDynamoDBContext /// Configured TransactWrite 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 ExecuteTransactWriteAsync(TransactWrite[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)); + Task ExecuteTransactWriteAsync(ITransactWrite[] transactionParts, CancellationToken cancellationToken = default(CancellationToken)); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactWrite.Async.cs index f905dd149298..4910c851591d 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactWrite.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/TransactWrite.Async.cs @@ -18,46 +18,48 @@ namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for writing/deleting/version-checking multiple items - /// in a single DynamoDB table in a transaction. - /// - public abstract partial class TransactWrite + public partial interface ITransactWrite { - #region Public methods - /// /// Executes a server call to write/delete/version-check the items requested 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. - public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) + Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public abstract partial class TransactWrite : ITransactWrite + { + /// + public abstract Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class TransactWrite : TransactWrite, ITransactWrite + { + /// + public override Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } - /// - /// Class for writing/deleting/version-checking multiple items in multiple DynamoDB tables, - /// using multiple strongly-typed TransactWrite objects. - /// - public partial class MultiTableTransactWrite + public partial interface IMultiTableTransactWrite { - #region Public methods - /// /// Executes a multi-table transaction request against all configured TransactWrite objects. /// /// 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 ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class MultiTableTransactWrite : IMultiTableTransactWrite + { + /// public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } } 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 21cff9c72e95..4207dc5833c6 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -202,11 +202,8 @@ public void ExecuteBatchWrite(params IBatchWrite[] batches) #region Transact Write - /// - /// Issues a transactional write request with multiple TransactWrite objects. - /// - /// Configured TransactWrite objects. - public void ExecuteTransactWrite(params TransactWrite[] transactionParts) + /// + public void ExecuteTransactWrite(params ITransactWrite[] transactionParts) { MultiTableTransactWrite transaction = new MultiTableTransactWrite(transactionParts); transaction.Execute(); 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 1655c635d095..1c8c6b36d67b 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -396,7 +396,7 @@ partial interface IDynamoDBContext /// Issues a transactional write request with multiple TransactWrite objects. /// /// Configured TransactWrite objects. - void ExecuteTransactWrite(params TransactWrite[] transactionParts); + void ExecuteTransactWrite(params ITransactWrite[] transactionParts); #endregion diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactWrite.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactWrite.Sync.cs index bb6242eaff20..4b166e850d38 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactWrite.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/TransactWrite.Sync.cs @@ -15,41 +15,43 @@ namespace Amazon.DynamoDBv2.DataModel { - /// - /// Represents a non-generic object for writing/deleting/version-checking multiple items - /// in a single DynamoDB table in a transaction. - /// - public abstract partial class TransactWrite + public partial interface ITransactWrite { - #region Public methods - /// /// Executes a server call to write/delete/version-check the items requested in a transaction. /// - public void Execute() + void Execute(); + } + + public abstract partial class TransactWrite : ITransactWrite + { + /// + public abstract void Execute(); + } + + public partial class TransactWrite : TransactWrite, ITransactWrite + { + /// + public override void Execute() { ExecuteHelper(); } - - #endregion } - /// - /// Class for writing/deleting/version-checking multiple items in multiple DynamoDB tables, - /// using multiple strongly-typed TransactWrite objects. - /// - public partial class MultiTableTransactWrite + public partial interface IMultiTableTransactWrite { - #region Public methods - /// /// Executes a multi-table transaction request against all configured TransactWrite objects. /// + void Execute(); + } + + public partial class MultiTableTransactWrite : IMultiTableTransactWrite + { + /// public void Execute() { ExecuteHelper(); } - - #endregion } } diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactWriteTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactWriteTests.cs new file mode 100644 index 000000000000..24eef4f9602f --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/TransactWriteTests.cs @@ -0,0 +1,121 @@ +using Amazon.DynamoDBv2.DataModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; + +namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests +{ + [TestClass] + public class TransactWriteTests + { + [TestMethod] + public void TestMockability_TransactWrite() + { + var itemsToSave = new List(); + var inMemoryTable = new List(); + + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateTransactWrite()) + .Returns(CreateTransactWriteMock(itemsToSave, inMemoryTable)); + + var ddbContext = mockContext.Object; + var transactWrite = ddbContext.CreateTransactWrite(); + + Assert.AreEqual(0, inMemoryTable.Count); + Assert.AreEqual(0, itemsToSave.Count); + + transactWrite.AddSaveItem("item1"); + transactWrite.AddSaveItem("item2"); + Assert.AreEqual(2, itemsToSave.Count); + Assert.AreEqual(0, inMemoryTable.Count); + + transactWrite.Execute(); + Assert.AreEqual(0, itemsToSave.Count); + Assert.AreEqual(2, inMemoryTable.Count); + Assert.IsTrue(inMemoryTable.Contains("item1")); + Assert.IsTrue(inMemoryTable.Contains("item2")); + } + + [TestMethod] + public void TestMockability_MultiTableTransactWrite() + { + var itemsToSave_table1 = new List(); + var inMemory_table1 = new List(); + var transactWrite_table1 = CreateTransactWriteMock(itemsToSave_table1, inMemory_table1); + transactWrite_table1.AddSaveItem("item1"); + + var itemsToSave_table2 = new List(); + var inMemory_table2 = new List(); + var transactWrite_table2 = CreateTransactWriteMock(itemsToSave_table2, inMemory_table2); + transactWrite_table2.AddSaveItem("item2"); + + var mockContext = new Mock(); + mockContext + .Setup(x => x.CreateMultiTableTransactWrite()) + .Returns(CreateMultiTableTransactWriteMock()); + + var ddbContext = mockContext.Object; + var multiTransactWrite = ddbContext.CreateMultiTableTransactWrite(); + 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.IsTrue(inMemory_table1.Contains("item1")); + Assert.IsTrue(inMemory_table2.Contains("item2")); + } + + public ITransactWrite CreateTransactWriteMock(List itemsToSave, List inMemoryTable) + { + var transactWrite = new Mock>(); + + transactWrite + .Setup(x => x.AddSaveItem(It.IsAny())) + .Callback((T item) => itemsToSave.Add(item)); + + transactWrite. + Setup(x => x.Execute()) + .Callback(() => + { + foreach (var item in itemsToSave) + { + inMemoryTable.Add(item); + } + + itemsToSave.Clear(); + }); + + return transactWrite.Object; + } + + public IMultiTableTransactWrite CreateMultiTableTransactWriteMock() + { + var multiTransactWrite = new Mock(); + var transactionParts = new List(); + + multiTransactWrite + .Setup(x => x.AddTransactionPart(It.IsAny())) + .Callback((ITransactWrite transactionPart) => + { + transactionParts.Add(transactionPart); + }); + + multiTransactWrite + .Setup(x => x.Execute()) + .Callback(() => + { + foreach (var batch in transactionParts) + { + batch.Execute(); + } + }); + + return multiTransactWrite.Object; + } + } +} From 1de686b7a6a4f6b017bcc9d206e17c559df1b376 Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Wed, 21 Aug 2024 10:00:51 -0700 Subject: [PATCH 5/7] Add the ability to mock AsyncSearch operations (#3437) --- .../Custom/DataModel/AsyncSearch.cs | 60 ++++++------ .../DataModel/_async/AsyncSearch.Async.cs | 40 ++++---- .../Custom/DataModel/_async/Context.Async.cs | 30 +++--- .../_async/IDynamoDBContext.Async.cs | 30 +++--- .../MockabilityTests/AsyncSearchTests.cs | 93 +++++++++++++++++++ 5 files changed, 171 insertions(+), 82 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/AsyncSearchTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/AsyncSearch.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/AsyncSearch.cs index e08008c8dc50..159c1281be09 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/AsyncSearch.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/AsyncSearch.cs @@ -13,18 +13,38 @@ * permissions and limitations under the License. */ -using Amazon.DynamoDBv2.DataModel; using Amazon.DynamoDBv2.DocumentModel; namespace Amazon.DynamoDBv2.DataModel { + /// + /// Interface retrieving search results (Query or Scan) + /// from DynamoDB. + /// + public partial interface IAsyncSearch + { + /// + /// Flag that, if true, indicates that the search is done + /// + bool IsDone { 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. + /// + string PaginationToken { get; } + } + /// /// A strongly-typed object for retrieving search results (Query or Scan) /// from DynamoDB. /// - public partial class AsyncSearch + public partial class AsyncSearch : IAsyncSearch { - #region Constructor + private Search _documentSearch { get; set; } + private DynamoDBContext _sourceContext { get; set; } + private DynamoDBFlatConfig _config { get; set; } /// /// This constructor is used for mocking. Users that want to mock AsyncSearch can create a subclass of AsyncSearch and make a public parameterless constructor. @@ -36,47 +56,27 @@ protected AsyncSearch() internal AsyncSearch(DynamoDBContext source, DynamoDBContext.ContextSearch contextSearch) { - SourceContext = source; - DocumentSearch = contextSearch.Search; - Config = contextSearch.FlatConfig; + _sourceContext = source; + _documentSearch = contextSearch.Search; + _config = contextSearch.FlatConfig; } - #endregion - - #region Private members - - private Search DocumentSearch { get; set; } - private DynamoDBContext SourceContext { get; set; } - private DynamoDBFlatConfig Config { get; set; } - - #endregion - - #region Public properties - - /// - /// Flag that, if true, indicates that the search is done - /// + /// public virtual bool IsDone { get { - return DocumentSearch.IsDone; + return _documentSearch.IsDone; } } - /// - /// 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 virtual string PaginationToken { get { - return DocumentSearch.PaginationToken; + return _documentSearch.PaginationToken; } } - - #endregion } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/AsyncSearch.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/AsyncSearch.Async.cs index 8945c588fabd..c37d83a73c6d 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/AsyncSearch.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/AsyncSearch.Async.cs @@ -18,21 +18,10 @@ using System.Threading; using System.Threading.Tasks; -using Amazon.Runtime.Internal; -using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.DataModel; - namespace Amazon.DynamoDBv2.DataModel { - /// - /// A strongly-typed object for retrieving search results (Query or Scan) - /// from DynamoDB. - /// - /// - public partial class AsyncSearch + public partial interface IAsyncSearch { - #region Async public - /// /// Initiates the asynchronous execution to get the next set of results from DynamoDB. /// @@ -45,12 +34,7 @@ public partial class AsyncSearch /// A Task that can be used to poll or wait for results, or both. /// Results will include the next set of result items from DynamoDB. /// - public virtual async Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - var documents = await DocumentSearch.GetNextSetHelperAsync(cancellationToken).ConfigureAwait(false); - List items = SourceContext.FromDocumentsHelper(documents, this.Config).ToList(); - return items; - } + Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken)); /// /// Initiates the asynchronous execution to get all the remaining results from DynamoDB. @@ -60,13 +44,25 @@ public partial class AsyncSearch /// A Task that can be used to poll or wait for results, or both. /// Results will include the remaining result items from DynamoDB. /// - public virtual async Task> GetRemainingAsync(CancellationToken cancellationToken = default(CancellationToken)) + Task> GetRemainingAsync(CancellationToken cancellationToken = default(CancellationToken)); + } + + public partial class AsyncSearch : IAsyncSearch + { + /// + public virtual async Task> GetNextSetAsync(CancellationToken cancellationToken = default(CancellationToken)) { - var documents = await DocumentSearch.GetRemainingHelperAsync(cancellationToken).ConfigureAwait(false); - List items = SourceContext.FromDocumentsHelper(documents, this.Config).ToList(); + var documents = await _documentSearch.GetNextSetHelperAsync(cancellationToken).ConfigureAwait(false); + List items = _sourceContext.FromDocumentsHelper(documents, this._config).ToList(); return items; } - #endregion + /// + public virtual async Task> GetRemainingAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + var documents = await _documentSearch.GetRemainingHelperAsync(cancellationToken).ConfigureAwait(false); + List items = _sourceContext.FromDocumentsHelper(documents, this._config).ToList(); + return items; + } } } diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs index 6d5ca468ebf3..731287ef7fda 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -245,7 +245,7 @@ public Task ExecuteBatchGetAsync(params IBatchGet[] batches) #region Scan async /// - public AsyncSearch ScanAsync(IEnumerable conditions) + public IAsyncSearch ScanAsync(IEnumerable conditions) { var scan = ConvertScan(conditions, null); return FromSearchAsync(scan); @@ -253,21 +253,21 @@ public AsyncSearch ScanAsync(IEnumerable conditions) /// [Obsolete("Use the ScanAsync overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to ScanAsync.")] - public AsyncSearch ScanAsync(IEnumerable conditions, DynamoDBOperationConfig operationConfig = null) + public IAsyncSearch ScanAsync(IEnumerable conditions, DynamoDBOperationConfig operationConfig = null) { var scan = ConvertScan(conditions, operationConfig); return FromSearchAsync(scan); } /// - public AsyncSearch ScanAsync(IEnumerable conditions, ScanConfig scanConfig) + public IAsyncSearch ScanAsync(IEnumerable conditions, ScanConfig scanConfig) { var scan = ConvertScan(conditions, scanConfig?.ToDynamoDBOperationConfig()); return FromSearchAsync(scan); } /// - public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig) + public IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig) { if (scanConfig == null) throw new ArgumentNullException("scanConfig"); @@ -277,7 +277,7 @@ public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig) /// [Obsolete("Use the FromScanAsync overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromScanAsync.")] - public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null) + public IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null) { if (scanConfig == null) throw new ArgumentNullException("scanConfig"); @@ -286,7 +286,7 @@ public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBO } /// - public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig) + public IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig) { if (scanConfig == null) throw new ArgumentNullException("scanConfig"); @@ -299,7 +299,7 @@ public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanC #region Query async /// - public AsyncSearch QueryAsync(object hashKeyValue) + public IAsyncSearch QueryAsync(object hashKeyValue) { var query = ConvertQueryByValue(hashKeyValue, null, null); return FromSearchAsync(query); @@ -307,21 +307,21 @@ public AsyncSearch QueryAsync(object hashKeyValue) /// [Obsolete("Use the QueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to QueryAsync.")] - public AsyncSearch QueryAsync(object hashKeyValue, DynamoDBOperationConfig operationConfig = null) + public IAsyncSearch QueryAsync(object hashKeyValue, DynamoDBOperationConfig operationConfig = null) { var query = ConvertQueryByValue(hashKeyValue, null, operationConfig); return FromSearchAsync(query); } /// - public AsyncSearch QueryAsync(object hashKeyValue, QueryConfig queryConfig) + public IAsyncSearch QueryAsync(object hashKeyValue, QueryConfig queryConfig) { var query = ConvertQueryByValue(hashKeyValue, null, queryConfig?.ToDynamoDBOperationConfig()); return FromSearchAsync(query); } /// - public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values) + public IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values) { if (values == null) throw new ArgumentNullException("values"); @@ -332,7 +332,7 @@ public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnum /// [Obsolete("Use the QueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to QueryAsync.")] - public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig = null) + public IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig = null) { if (values == null) throw new ArgumentNullException("values"); @@ -342,7 +342,7 @@ public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnum } /// - public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig) + public IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig) { if (values == null) throw new ArgumentNullException("values"); @@ -352,7 +352,7 @@ public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnum } /// - public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig) + public IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig) { if (queryConfig == null) throw new ArgumentNullException("queryConfig"); @@ -362,7 +362,7 @@ public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig) /// [Obsolete("Use the FromQueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromQueryAsync.")] - public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig = null) + public IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig = null) { if (queryConfig == null) throw new ArgumentNullException("queryConfig"); @@ -371,7 +371,7 @@ public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, Dynamo } /// - public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig) + public IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig) { if (queryConfig == null) throw new ArgumentNullException("queryConfig"); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs index 848d12b8aa69..98a1bee4674d 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -482,7 +482,7 @@ partial interface IDynamoDBContext /// Conditions that the results should meet. /// /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch ScanAsync(IEnumerable conditions); + IAsyncSearch ScanAsync(IEnumerable conditions); /// /// Configures an async Scan operation against DynamoDB, finding items @@ -496,7 +496,7 @@ partial interface IDynamoDBContext /// AsyncSearch which can be used to retrieve DynamoDB data. [Obsolete("Use the ScanAsync overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to ScanAsync.")] - AsyncSearch ScanAsync(IEnumerable conditions, DynamoDBOperationConfig operationConfig = null); + IAsyncSearch ScanAsync(IEnumerable conditions, DynamoDBOperationConfig operationConfig = null); /// /// Configures an async Scan operation against DynamoDB, finding items @@ -508,7 +508,7 @@ partial interface IDynamoDBContext /// /// Config object that can be used to override properties on the table's context for this request. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch ScanAsync(IEnumerable conditions, ScanConfig scanConfig); + IAsyncSearch ScanAsync(IEnumerable conditions, ScanConfig scanConfig); /// /// Configures an async Scan operation against DynamoDB, finding items @@ -517,7 +517,7 @@ partial interface IDynamoDBContext /// Type of object. /// Scan request object. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch FromScanAsync(ScanOperationConfig scanConfig); + IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig); /// /// Configures an async Scan operation against DynamoDB, finding items @@ -528,7 +528,7 @@ partial interface IDynamoDBContext /// Config object which can be used to override the table used. /// AsyncSearch which can be used to retrieve DynamoDB data. [Obsolete("Use the FromScanAsync overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromScanAsync.")] - AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null); + IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null); /// /// Configures an async Scan operation against DynamoDB, finding items @@ -538,7 +538,7 @@ partial interface IDynamoDBContext /// Scan request object. /// Config object that can be used to override properties on the table's context for this request. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig); + IAsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig); #endregion @@ -551,7 +551,7 @@ partial interface IDynamoDBContext /// Type of object. /// Hash key of the items to query. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch QueryAsync(object hashKeyValue); + IAsyncSearch QueryAsync(object hashKeyValue); /// /// Configures an async Query operation against DynamoDB, finding items @@ -562,7 +562,7 @@ partial interface IDynamoDBContext /// Config object which can be used to override the table used. /// AsyncSearch which can be used to retrieve DynamoDB data. [Obsolete("Use the QueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to QueryAsync.")] - AsyncSearch QueryAsync(object hashKeyValue, DynamoDBOperationConfig operationConfig = null); + IAsyncSearch QueryAsync(object hashKeyValue, DynamoDBOperationConfig operationConfig = null); /// /// Configures an async Query operation against DynamoDB, finding items @@ -572,7 +572,7 @@ partial interface IDynamoDBContext /// Hash key of the items to query. /// Config object that can be used to override properties on the table's context for this request. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch QueryAsync(object hashKeyValue, QueryConfig queryConfig); + IAsyncSearch QueryAsync(object hashKeyValue, QueryConfig queryConfig); /// /// Configures an async Query operation against DynamoDB, finding items @@ -587,7 +587,7 @@ partial interface IDynamoDBContext /// For QueryOperator.Betwee, values should be two values. /// /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values); + IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values); /// /// Configures an async Query operation against DynamoDB, finding items @@ -604,7 +604,7 @@ partial interface IDynamoDBContext /// Config object which can be used to override the table used. /// AsyncSearch which can be used to retrieve DynamoDB data. [Obsolete("Use the QueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to QueryAsync.")] - AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig = null); + IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig = null); /// /// Configures an async Query operation against DynamoDB, finding items @@ -620,7 +620,7 @@ partial interface IDynamoDBContext /// /// Config object that can be used to override properties on the table's context for this request. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig); + IAsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig); /// /// Configures an async Query operation against DynamoDB using a mid-level document model @@ -629,7 +629,7 @@ partial interface IDynamoDBContext /// Type of object. /// Mid-level, document model query request object. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig); + IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig); /// /// Configures an async Query operation against DynamoDB, finding items @@ -640,7 +640,7 @@ partial interface IDynamoDBContext /// Config object which can be used to override the table used. /// AsyncSearch which can be used to retrieve DynamoDB data. [Obsolete("Use the FromQueryAsync overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromQueryAsync.")] - AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig = null); + IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig = null); /// /// Configures an async Query operation against DynamoDB using a mid-level document model @@ -650,7 +650,7 @@ partial interface IDynamoDBContext /// Mid-level, document model query request object. /// Config object that can be used to override properties on the table's context for this request. /// AsyncSearch which can be used to retrieve DynamoDB data. - AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig); + IAsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig); #endregion } diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/AsyncSearchTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/AsyncSearchTests.cs new file mode 100644 index 000000000000..825a203e9179 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/AsyncSearchTests.cs @@ -0,0 +1,93 @@ +using Amazon.DynamoDBv2.DataModel; +using Amazon.DynamoDBv2.DocumentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests +{ + [TestClass] + public class AsyncSearchTests + { + [TestMethod] + public async Task TestMockability_ScanAsync() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.ScanAsync(It.IsAny>())) + .Returns(CreateMockAsyncSearch(new List { "item1", "item2" })); + + var ddbContext = mockContext.Object; + var asyncSearch = ddbContext.ScanAsync(null); + + var results = await asyncSearch.GetNextSetAsync(); + Assert.AreEqual(2, results.Count); + Assert.AreEqual("item1", results[0]); + Assert.AreEqual("item2", results[1]); + } + + [TestMethod] + public async Task TestMockability_FromScanAsync() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.FromScanAsync(It.IsAny())) + .Returns(CreateMockAsyncSearch(new List { "item1", "item2" })); + + var ddbContext = mockContext.Object; + var asyncSearch = ddbContext.FromScanAsync(null); + + var results = await asyncSearch.GetNextSetAsync(); + Assert.AreEqual(2, results.Count); + Assert.AreEqual("item1", results[0]); + Assert.AreEqual("item2", results[1]); + } + + [TestMethod] + public async Task TestMockability_QueryAsync() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.QueryAsync(It.IsAny())) + .Returns(CreateMockAsyncSearch(new List { "item1", "item2" })); + + var ddbContext = mockContext.Object; + var asyncSearch = ddbContext.QueryAsync(null); + + var results = await asyncSearch.GetNextSetAsync(); + Assert.AreEqual(2, results.Count); + Assert.AreEqual("item1", results[0]); + Assert.AreEqual("item2", results[1]); + } + + [TestMethod] + public async Task TestMockability_FromQueryAsync() + { + var mockContext = new Mock(); + mockContext + .Setup(x => x.FromQueryAsync(It.IsAny())) + .Returns(CreateMockAsyncSearch(new List { "item1", "item2" })); + + var ddbContext = mockContext.Object; + var asyncSearch = ddbContext.FromQueryAsync(null); + + var results = await asyncSearch.GetNextSetAsync(); + Assert.AreEqual(2, results.Count); + Assert.AreEqual("item1", results[0]); + Assert.AreEqual("item2", results[1]); + } + + public IAsyncSearch CreateMockAsyncSearch(List items) + { + var mockAsyncSearch = new Mock>(); + + mockAsyncSearch + .Setup(x => x.GetNextSetAsync(It.IsAny())) + .Returns(Task.FromResult(items)); + + return mockAsyncSearch.Object; + } + } +} From 886ed9e38023398c274681aa6a5339e8a936c8cd Mon Sep 17 00:00:00 2001 From: Malhar Khimsaria <96malhar@gmail.com> Date: Wed, 21 Aug 2024 15:10:35 -0700 Subject: [PATCH 6/7] Add the ability to mock document model operations in DynamoDB (#3446) * Add the ability to mock DocumentBatchGet and MultiTableDocumentBatchGet operations * Add the ability to mock DocumentBatchWrite and MultiTableDocumentBatchWrite operations * Add the ability to mock DocumentTransactGet and MultiTableDocumentTransactGet operations * Add the ability to mock DocumentTransactWrite and MultiTableDocumentTransactWrite operations * Add the ability to mock Search operations in Document model * Add the ability to mock Table operations in Document model * Fix typos --- .../DynamoDBv2/Custom/DataModel/BatchWrite.cs | 5 +- .../Custom/DataModel/ContextInternal.cs | 18 +- .../Custom/DataModel/TransactGet.cs | 5 +- .../Custom/DataModel/TransactWrite.cs | 5 +- .../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 | 157 ++++--- .../DocumentModel/DocumentBatchWrite.cs | 133 ++++-- .../DocumentModel/DocumentTransactGet.cs | 195 ++++++--- .../DocumentModel/DocumentTransactWrite.cs | 386 ++++++++++------ .../DynamoDBv2/Custom/DocumentModel/Search.cs | 166 ++++--- .../DynamoDBv2/Custom/DocumentModel/Table.cs | 414 +++++++++++------- .../_async/DocumentBatchGet.Async.cs | 37 +- .../_async/DocumentBatchWrite.Async.cs | 37 +- .../_async/DocumentTransactGet.Async.cs | 30 +- .../_async/DocumentTransactWrite.Async.cs | 32 +- .../DocumentModel/_async/Search.Async.cs | 37 +- .../DocumentModel/_async/Table.Async.cs | 282 ++++++++---- .../_bcl/DocumentBatchGet.Sync.cs | 39 +- .../_bcl/DocumentBatchWrite.Sync.cs | 39 +- .../_bcl/DocumentTransactGet.Sync.cs | 30 +- .../_bcl/DocumentTransactWrite.Sync.cs | 32 +- .../Custom/DocumentModel/_bcl/Search.Sync.cs | 33 +- .../Custom/DocumentModel/_bcl/Table.Sync.cs | 371 +++++++++------- .../DynamoDBv2/IntegrationTests/Cache.cs | 2 +- .../IntegrationTests/DocumentTests.cs | 74 ++-- .../DynamoDBv2/IntegrationTests/Extensions.cs | 2 +- .../DynamoDBv2/IntegrationTests/JSONTests.cs | 6 +- .../DynamoDBv2/IntegrationTests/TTLTests.cs | 10 +- .../MockabilityTests/DocumentBatchGetTests.cs | 155 +++++++ .../DocumentBatchWriteTests.cs | 118 +++++ .../MockabilityTests/DocumentSearchTests.cs | 72 +++ .../DocumentTransactGetTests.cs | 122 ++++++ .../DocumentTransactWriteTests.cs | 117 +++++ 36 files changed, 2159 insertions(+), 1031 deletions(-) create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.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/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs index 3d0431f664cc..b692b1bc806a 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs @@ -192,7 +192,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; @@ -1183,7 +1183,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); } @@ -1192,7 +1194,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); } @@ -1201,7 +1205,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); } @@ -1246,7 +1252,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/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/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/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 bcec76d707f6..aed84740d092 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. + /// + IMultiTableDocumentBatchGet 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 IMultiTableDocumentBatchGet 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/DocumentBatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentBatchWrite.cs index 2d4a4e882928..63122f863ab9 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. + /// + IMultiTableDocumentBatchWrite 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 IMultiTableDocumentBatchWrite 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/DocumentTransactGet.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactGet.cs index 354b87c14a98..8a77e44bf89e 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. + /// + IMultiTableDocumentTransactGet 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 IMultiTableDocumentTransactGet 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/DocumentTransactWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/DocumentTransactWrite.cs index cff407032037..3ec32bd4c5b8 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. + /// + IMultiTableDocumentTransactWrite 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 IMultiTableDocumentTransactWrite 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 transaction parts 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 transaction parts 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 transaction parts 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/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 17c04ce926c9..7c67a4b0a281 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 @@ -444,7 +641,7 @@ public static void ClearTableCache() /// Configuration to use for the table. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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(); @@ -650,7 +847,7 @@ internal static Table CreateTableFromItemStorageConfig(IAmazonDynamoDB client, T /// Name of the table. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName) + public static ITable LoadTable(IAmazonDynamoDB ddbClient, string tableName) { return LoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, false); } @@ -666,7 +863,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName) /// Conversion to use for converting .NET values to DynamoDB values. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -682,7 +879,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam /// If the property is false, empty string values will be interpreted as null values. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -699,7 +896,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool /// If the property is false, empty string values will be interpreted as null values. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); @@ -721,7 +918,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam /// IAmazonDynamoDB.DescribeTable(string) internally to populate the cache. /// Table object representing the specified table. [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); @@ -743,7 +940,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam /// True if table was successfully loaded; otherwise false. /// [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -762,7 +959,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out /// True if table was successfully loaded; otherwise false. /// [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -781,7 +978,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, Dyn /// True if table was successfully loaded; otherwise false. /// [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -801,7 +998,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, boo /// True if table was successfully loaded; otherwise false. /// [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); } @@ -829,7 +1026,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, @@ -854,11 +1051,12 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, /// True if table was successfully loaded; otherwise false. /// [Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")] - 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); @@ -869,46 +1067,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); @@ -1397,28 +1580,14 @@ 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 Search Scan(ScanFilter filter) + /// + 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 Search Scan(Expression filterExpression) + /// + public ISearch Scan(Expression filterExpression) { ScanOperationConfig config = new ScanOperationConfig { @@ -1429,15 +1598,8 @@ public Search 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 Search Scan(ScanOperationConfig config) + /// + public ISearch Scan(ScanOperationConfig config) { var currentConfig = config ?? new ScanOperationConfig(); @@ -1471,16 +1633,8 @@ public Search 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 Search Query(Primitive hashKey, QueryFilter filter) + /// + public ISearch Query(Primitive hashKey, QueryFilter filter) { string hashKeyName = this.HashKeys[0]; QueryFilter fullFilter = new QueryFilter(filter); @@ -1490,16 +1644,8 @@ public Search 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 Search Query(Primitive hashKey, Expression filterExpression) + /// + public ISearch Query(Primitive hashKey, Expression filterExpression) { string hashKeyName = this.HashKeys[0]; @@ -1515,28 +1661,14 @@ public Search 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 Search Query(QueryFilter filter) + /// + 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 Search Query(QueryOperationConfig config) + /// + public ISearch Query(QueryOperationConfig config) { if (config == null) throw new ArgumentNullException("config"); @@ -1567,12 +1699,8 @@ public Search Query(QueryOperationConfig config) #region BatchGet - /// - /// Creates a DocumentBatchGet object for the current table, allowing - /// a batch-get operation against DynamoDB. - /// - /// Empty DocumentBatchGet object. - public DocumentBatchGet CreateBatchGet() + /// + public IDocumentBatchGet CreateBatchGet() { return new DocumentBatchGet(this); } @@ -1582,12 +1710,8 @@ public DocumentBatchGet CreateBatchGet() #region BatchWrite - /// - /// Creates a DocumentBatchWrite object for the current table, allowing - /// a batch-put/delete operation against DynamoDB. - /// - /// Empty DocumentBatchWrite object. - public DocumentBatchWrite CreateBatchWrite() + /// + public IDocumentBatchWrite CreateBatchWrite() { return new DocumentBatchWrite(this); } @@ -1597,12 +1721,8 @@ public DocumentBatchWrite CreateBatchWrite() #region TransactGet - /// - /// Creates a DocumentTransactGet object for the current table, allowing - /// a transactional get operation against DynamoDB. - /// - /// Empty DocumentTransactGet object. - public DocumentTransactGet CreateTransactGet() + /// + public IDocumentTransactGet CreateTransactGet() { return new DocumentTransactGet(this); } @@ -1612,12 +1732,8 @@ public DocumentTransactGet 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 DocumentTransactWrite CreateTransactWrite() + /// + public IDocumentTransactWrite CreateTransactWrite() { return new DocumentTransactWrite(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/_async/DocumentBatchWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_async/DocumentBatchWrite.Async.cs index 2a01e95897fa..aa791aceb1e8 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 : IMultiTableDocumentBatchWrite + { + /// public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { return ExecuteHelperAsync(cancellationToken); } - - #endregion } } 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/_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/_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/_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 /// 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, Primitive rangeKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) - { - return DeleteHelperAsync(MakeKey(hashKey, rangeKey), config, cancellationToken); - } + Task DeleteItemAsync(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)); /// /// Initiates the asynchronous execution of the DeleteItem operation. @@ -320,10 +252,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 DeleteItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken)) - { - return DeleteHelperAsync(MakeKey(key), null, cancellationToken); - } + Task DeleteItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken)); /// /// Initiates the asynchronous execution of the DeleteItem operation. @@ -332,6 +261,169 @@ 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. + Task DeleteItemAsync(IDictionary key, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)); + + #endregion + } + + public partial class Table : ITable + { + #region PutItemAsync + + /// + public Task PutItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken)) + { + return PutItemHelperAsync(doc, null, cancellationToken); + } + + + /// + public Task PutItemAsync(Document doc, PutItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return PutItemHelperAsync(doc, config, cancellationToken); + } + + #endregion + + #region GetItemAsync + + /// + public Task GetItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(hashKey, null), null, cancellationToken); + } + + /// + public Task GetItemAsync(Primitive hashKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(hashKey, null), config, cancellationToken); + } + + + /// + public Task GetItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(hashKey, rangeKey), null, cancellationToken); + } + + /// + public Task GetItemAsync(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(hashKey, rangeKey), config, cancellationToken); + } + + /// + public Task GetItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(key), null, cancellationToken); + } + + /// + public Task GetItemAsync(IDictionary key, GetItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return GetItemHelperAsync(MakeKey(key), config, cancellationToken); + } + + #endregion + + #region UpdateItemAsync + + /// + public Task UpdateItemAsync(Document doc, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, null, null, null, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, null, null, config, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, IDictionary key, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, MakeKey(key), null, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, IDictionary key, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, MakeKey(key), config, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, hashKey, null, null, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, Primitive hashKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, hashKey, null, config, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, hashKey, rangeKey, null, cancellationToken); + } + + /// + public Task UpdateItemAsync(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return UpdateHelperAsync(doc, hashKey, rangeKey, config, cancellationToken); + } + + + #endregion + + #region DeleteItemAsync + + /// + public Task DeleteItemAsync(Document document, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(document), null, cancellationToken); + } + + /// + public Task DeleteItemAsync(Document document, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(document), config, cancellationToken); + } + + /// + public Task DeleteItemAsync(Primitive hashKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(hashKey, null), null, cancellationToken); + } + + /// + public Task DeleteItemAsync(Primitive hashKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(hashKey, null), config, cancellationToken); + } + + /// + public Task DeleteItemAsync(Primitive hashKey, Primitive rangeKey, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(hashKey, rangeKey), null, cancellationToken); + } + + /// + public Task DeleteItemAsync(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(hashKey, rangeKey), config, cancellationToken); + } + + /// + public Task DeleteItemAsync(IDictionary key, CancellationToken cancellationToken = default(CancellationToken)) + { + return DeleteHelperAsync(MakeKey(key), null, cancellationToken); + } + + /// public Task DeleteItemAsync(IDictionary key, DeleteItemOperationConfig config, CancellationToken cancellationToken = default(CancellationToken)) { return DeleteHelperAsync(MakeKey(key), config, cancellationToken); 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..f43592e50f76 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 : IMultiTableDocumentBatchGet + { + /// public void Execute() { ExecuteHelper(); } - - #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/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/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/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/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Table.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Table.Sync.cs index 7c57bbd78dfe..31a26baa6bdf 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Table.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/_bcl/Table.Sync.cs @@ -13,19 +13,12 @@ * permissions and limitations under the License. */ -using System; - using Amazon.DynamoDBv2.Model; -using Amazon.Runtime; -using Amazon.Util; -using System.Linq; -using System.Threading; using System.Collections.Generic; -using System.Collections.ObjectModel; namespace Amazon.DynamoDBv2.DocumentModel { - public partial class Table + public partial interface ITable { #region PutItem @@ -35,10 +28,7 @@ public partial class Table /// Document to save. /// Configuration to use. /// Null or updated attributes, depending on config. - public Document PutItem(Document doc, PutItemOperationConfig config = null) - { - return PutItemHelper(doc, config); - } + Document PutItem(Document doc, PutItemOperationConfig config = null); /// /// Puts a document into DynamoDB, using optional configs. @@ -46,22 +36,10 @@ public Document PutItem(Document doc, PutItemOperationConfig config = null) /// Document to save. /// Configuration to use. /// True if put is successful or false if the condition in the config was not met. - public bool TryPutItem(Document doc, PutItemOperationConfig config = null) - { - try - { - PutItemHelper(doc, config); - return true; - } - catch (ConditionalCheckFailedException) - { - return false; - } - } + bool TryPutItem(Document doc, PutItemOperationConfig config = null); #endregion - #region GetItem /// @@ -70,10 +48,7 @@ public bool TryPutItem(Document doc, PutItemOperationConfig config = null) /// Hash key element of the document. /// Configuration to use. /// Document from DynamoDB. - public Document GetItem(Primitive hashKey, GetItemOperationConfig config = null) - { - return GetItem(hashKey, null, config); - } + Document GetItem(Primitive hashKey, GetItemOperationConfig config = null); /// /// Gets a document from DynamoDB by hash-and-range primary key, @@ -83,10 +58,7 @@ public Document GetItem(Primitive hashKey, GetItemOperationConfig config = null) /// Range key element of the document. /// Configuration to use. /// Document from DynamoDB. - public Document GetItem(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config = null) - { - return GetItemHelper(MakeKey(hashKey, rangeKey), config); - } + Document GetItem(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config = null); /// /// Gets a document from DynamoDB by key, using specified configs. @@ -94,14 +66,10 @@ public Document GetItem(Primitive hashKey, Primitive rangeKey, GetItemOperationC /// Key of the document. /// Configuration to use. /// Document from DynamoDB. - public Document GetItem(IDictionary key, GetItemOperationConfig config = null) - { - return GetItemHelper(MakeKey(key), config); - } + Document GetItem(IDictionary key, GetItemOperationConfig config = null); #endregion - #region UpdateItem /// @@ -111,10 +79,7 @@ public Document GetItem(IDictionary key, GetItemOperation /// Configuration to use. /// Null or updated attributes, depending on config. /// - public Document UpdateItem(Document doc, UpdateItemOperationConfig config = null) - { - return UpdateHelper(doc, MakeKey(doc), config); - } + Document UpdateItem(Document doc, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, using specified config. @@ -123,18 +88,7 @@ public Document UpdateItem(Document doc, UpdateItemOperationConfig config = null /// Configuration to use. /// True if updated or false if the condition in the config was not met. /// - public bool TryUpdateItem(Document doc, UpdateItemOperationConfig config = null) - { - try - { - UpdateHelper(doc, MakeKey(doc), config); - return true; - } - catch (ConditionalCheckFailedException) - { - return false; - } - } + bool TryUpdateItem(Document doc, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a key to identify the @@ -145,10 +99,7 @@ public bool TryUpdateItem(Document doc, UpdateItemOperationConfig config = null) /// Configuration to use. /// Null or updated attributes, depending on config. /// - public Document UpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null) - { - return UpdateHelper(doc, MakeKey(key), config); - } + Document UpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a key to identify the @@ -159,18 +110,7 @@ public Document UpdateItem(Document doc, IDictionary key, /// Configuration to use. /// True if updated or false if the condition in the config was not met. /// - public bool TryUpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null) - { - try - { - UpdateHelper(doc, MakeKey(key), config); - return true; - } - catch (ConditionalCheckFailedException) - { - return false; - } - } + bool TryUpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a hash primary key to identify @@ -181,10 +121,7 @@ public bool TryUpdateItem(Document doc, IDictionary key, /// Configuration to use. /// Null or updated attributes, depending on config. /// - public Document UpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null) - { - return UpdateHelper(doc, MakeKey(hashKey, null), config); - } + Document UpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a hash primary key to identify @@ -195,18 +132,7 @@ public Document UpdateItem(Document doc, Primitive hashKey, UpdateItemOperationC /// Configuration to use. /// True if updated or false if the condition in the config was not met. /// - public bool TryUpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null) - { - try - { - UpdateHelper(doc, MakeKey(hashKey, null), config); - return true; - } - catch (ConditionalCheckFailedException) - { - return false; - } - } + bool TryUpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a hash-and-range primary key to identify @@ -218,10 +144,7 @@ public bool TryUpdateItem(Document doc, Primitive hashKey, UpdateItemOperationCo /// Configuration to use. /// Null or updated attributes, depending on config. /// - public Document UpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null) - { - return UpdateHelper(doc, MakeKey(hashKey, rangeKey), config); - } + Document UpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null); /// /// Update a document in DynamoDB, with a hash-and-range primary key to identify @@ -233,6 +156,208 @@ public Document UpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, /// Configuration to use. /// True if updated or false if the condition in the config was not met. /// + bool TryUpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null); + + #endregion + + #region DeleteItem + + /// + /// Delete a document in DynamoDB, using specified configs. + /// + /// If the condition set on the config fails. + /// Document to delete. + /// Configuration to use. + /// Null or old attributes, depending on config. + Document DeleteItem(Document document, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, using specified configs. + /// + /// Document to delete. + /// Configuration to use. + /// True if deleted or false if the condition in the config was not met. + bool TryDeleteItem(Document document, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by hash-key, + /// using the specified configs. + /// + /// If the condition set on the config fails. + /// Hash key element of the document. + /// Configuration to use. + /// Null or old attributes, depending on config. + Document DeleteItem(Primitive hashKey, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by a hash primary key, + /// using specified configs. + /// + /// Hash key element of the document. + /// Configuration to use. + /// True if deleted or false if the condition in the config was not met. + bool TryDeleteItem(Primitive hashKey, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by hash-and-range primary key, + /// using the specified configs. + /// + /// If the condition set on the config fails. + /// Hash key element of the document. + /// Range key element of the document. + /// Configuration to use. + /// Null or old attributes, depending on config. + Document DeleteItem(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by hash-and-range primary key, + /// using the specified configs. + /// + /// Hash key element of the document. + /// Range key element of the document. + /// Configuration to use. + /// True if deleted or false if the condition in the config was not met. + bool TryDeleteItem(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by a key, using specified configs. + /// + /// If the condition set on the config fails. + /// Key of the document. + /// Configuration to use. + /// Null or old attributes, depending on config. + Document DeleteItem(IDictionary key, DeleteItemOperationConfig config = null); + + /// + /// Delete a document in DynamoDB, identified by a key, using specified configs. + /// + /// Key of the document. + /// Configuration to use. + /// True if deleted or false if the condition in the config was not met. + bool TryDeleteItem(IDictionary key, DeleteItemOperationConfig config = null); + + #endregion + } + + public partial class Table : ITable + { + #region PutItem + + /// + public Document PutItem(Document doc, PutItemOperationConfig config = null) + { + return PutItemHelper(doc, config); + } + + /// + public bool TryPutItem(Document doc, PutItemOperationConfig config = null) + { + try + { + PutItemHelper(doc, config); + return true; + } + catch (ConditionalCheckFailedException) + { + return false; + } + } + + #endregion + + + #region GetItem + + /// + public Document GetItem(Primitive hashKey, GetItemOperationConfig config = null) + { + return GetItem(hashKey, null, config); + } + + /// + public Document GetItem(Primitive hashKey, Primitive rangeKey, GetItemOperationConfig config = null) + { + return GetItemHelper(MakeKey(hashKey, rangeKey), config); + } + + /// + public Document GetItem(IDictionary key, GetItemOperationConfig config = null) + { + return GetItemHelper(MakeKey(key), config); + } + + #endregion + + + #region UpdateItem + + /// + public Document UpdateItem(Document doc, UpdateItemOperationConfig config = null) + { + return UpdateHelper(doc, MakeKey(doc), config); + } + + /// + public bool TryUpdateItem(Document doc, UpdateItemOperationConfig config = null) + { + try + { + UpdateHelper(doc, MakeKey(doc), config); + return true; + } + catch (ConditionalCheckFailedException) + { + return false; + } + } + + /// + public Document UpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null) + { + return UpdateHelper(doc, MakeKey(key), config); + } + + /// + public bool TryUpdateItem(Document doc, IDictionary key, UpdateItemOperationConfig config = null) + { + try + { + UpdateHelper(doc, MakeKey(key), config); + return true; + } + catch (ConditionalCheckFailedException) + { + return false; + } + } + + /// + public Document UpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null) + { + return UpdateHelper(doc, MakeKey(hashKey, null), config); + } + + /// + public bool TryUpdateItem(Document doc, Primitive hashKey, UpdateItemOperationConfig config = null) + { + try + { + UpdateHelper(doc, MakeKey(hashKey, null), config); + return true; + } + catch (ConditionalCheckFailedException) + { + return false; + } + } + + /// + public Document UpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null) + { + return UpdateHelper(doc, MakeKey(hashKey, rangeKey), config); + } + + /// public bool TryUpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null) { try @@ -251,24 +376,13 @@ public bool TryUpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, U #region DeleteItem - /// - /// Delete a document in DynamoDB, using specified configs. - /// - /// If the condition set on the config fails. - /// Document to delete. - /// Configuration to use. - /// Null or old attributes, depending on config. + /// public Document DeleteItem(Document document, DeleteItemOperationConfig config = null) { return DeleteHelper(MakeKey(document), config); } - /// - /// Delete a document in DynamoDB, using specified configs. - /// - /// Document to delete. - /// Configuration to use. - /// True if deleted or false if the condition in the config was not met. + /// public bool TryDeleteItem(Document document, DeleteItemOperationConfig config = null) { try @@ -282,26 +396,13 @@ public bool TryDeleteItem(Document document, DeleteItemOperationConfig config = } } - /// - /// Delete a document in DynamoDB, identified by hash-key, - /// using the specified configs. - /// - /// If the condition set on the config fails. - /// Hash key element of the document. - /// Configuration to use. - /// Null or old attributes, depending on config. + /// public Document DeleteItem(Primitive hashKey, DeleteItemOperationConfig config = null) { return DeleteHelper(MakeKey(hashKey, null), config); } - /// - /// Delete a document in DynamoDB, identified by a hash primary key, - /// using specified configs. - /// - /// Hash key element of the document. - /// Configuration to use. - /// True if deleted or false if the condition in the config was not met. + /// public bool TryDeleteItem(Primitive hashKey, DeleteItemOperationConfig config = null) { try @@ -315,28 +416,13 @@ public bool TryDeleteItem(Primitive hashKey, DeleteItemOperationConfig config = } } - /// - /// Delete a document in DynamoDB, identified by hash-and-range primary key, - /// using the specified configs. - /// - /// If the condition set on the config fails. - /// Hash key element of the document. - /// Range key element of the document. - /// Configuration to use. - /// Null or old attributes, depending on config. + /// public Document DeleteItem(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config = null) { return DeleteHelper(MakeKey(hashKey, rangeKey), config); } - /// - /// Delete a document in DynamoDB, identified by hash-and-range primary key, - /// using the specified configs. - /// - /// Hash key element of the document. - /// Range key element of the document. - /// Configuration to use. - /// True if deleted or false if the condition in the config was not met. + /// public bool TryDeleteItem(Primitive hashKey, Primitive rangeKey, DeleteItemOperationConfig config = null) { try @@ -350,24 +436,13 @@ public bool TryDeleteItem(Primitive hashKey, Primitive rangeKey, DeleteItemOpera } } - /// - /// Delete a document in DynamoDB, identified by a key, using specified configs. - /// - /// If the condition set on the config fails. - /// Key of the document. - /// Configuration to use. - /// Null or old attributes, depending on config. + /// public Document DeleteItem(IDictionary key, DeleteItemOperationConfig config = null) { return DeleteHelper(MakeKey(key), config); } - /// - /// Delete a document in DynamoDB, identified by a key, using specified configs. - /// - /// Key of the document. - /// Configuration to use. - /// True if deleted or false if the condition in the config was not met. + /// public bool TryDeleteItem(IDictionary key, DeleteItemOperationConfig config = null) { try diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/Cache.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/Cache.cs index 6f48710b2e86..5c4925d967b3 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/Cache.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/Cache.cs @@ -100,7 +100,7 @@ public void MultipleClientsTest() Table.ClearTableCache(); var tableName = testTableName; - Table table; + ITable table; using (var nc = new AmazonDynamoDBClient()) { #pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs index 9631ff8038d4..234b5a0c97e1 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs @@ -26,9 +26,9 @@ public void TestTableOperations() // Clear tables CleanupTables(); - Table hashTable; - Table hashRangeTable; - Table numericHashRangeTable; + ITable hashTable; + ITable hashRangeTable; + ITable numericHashRangeTable; // Load tables using provided conversion schema LoadTables(conversion, out hashTable, out hashRangeTable, out numericHashRangeTable); @@ -161,7 +161,7 @@ public void TestTableOperationsViaBuilder() } } - private void TestAsDateTimeUtc(Table numericHashRangeTable) + private void TestAsDateTimeUtc(ITable numericHashRangeTable) { var config = new TableConfig(numericHashRangeTable.TableName) { @@ -191,7 +191,7 @@ private void TestAsDateTimeUtc(Table numericHashRangeTable) ApproximatelyEqual(currTimeUtc, storedDoc["NonEpochDate"].AsDateTimeUtc()); } - private void TestEmptyString(Table hashTable) + private void TestEmptyString(ITable hashTable) { var companyInfo = new DynamoDBList(); companyInfo.Add(string.Empty); @@ -224,7 +224,7 @@ private void TestEmptyString(Table hashTable) Assert.AreEqual(string.Empty, savedProduct["Map"].AsDocument()["Position"].AsString()); } - private void TestPagination(Table hashRangeTable) + private void TestPagination(ITable hashRangeTable) { var itemCount = 10; var batchWrite = hashRangeTable.CreateBatchWrite(); @@ -296,7 +296,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 @@ -316,7 +316,7 @@ private static int VerifyPagination(Search search, List tokens) return count; } - private void TestEmptyCollections(Table hashTable) + private void TestEmptyCollections(ITable hashTable) { Document doc = new Document(); doc["Id"] = 1; @@ -339,7 +339,7 @@ private void TestEmptyCollections(Table hashTable) Assert.AreEqual(0, listEntry.AsDynamoDBList().Entries.Count); } - private void TestHashTable(Table hashTable, DynamoDBEntryConversion conversion) + private void TestHashTable(ITable hashTable, DynamoDBEntryConversion conversion) { // Put an item Document doc = new Document(); @@ -564,7 +564,7 @@ private void TestHashTable(Table hashTable, DynamoDBEntryConversion conversion) items = hashTable.Scan(new ScanFilter()).GetRemaining(); Assert.AreEqual(0, items.Count); } - private void TestHashRangeTable(Table hashRangeTable, DynamoDBEntryConversion conversion) + private void TestHashRangeTable(ITable hashRangeTable, DynamoDBEntryConversion conversion) { // Put an item Document doc1 = new Document(); @@ -777,7 +777,7 @@ private void TestHashRangeTable(Table hashRangeTable, DynamoDBEntryConversion co }).GetRemaining(); Assert.AreEqual(1, items.Count); } - private void TestLargeBatchOperations(Table hashTable) + private void TestLargeBatchOperations(ITable hashTable) { int itemCount = 30; int itemSize = 40 * 1024; @@ -825,7 +825,7 @@ private void TestLargeBatchOperations(Table hashTable) Assert.AreEqual(0, items.Count); } - private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTable) + private void TestMultiTableDocumentBatchWrite(ITable hashTable, ITable hashRangeTable) { var multiTableDocumentBatchWrite = new MultiTableDocumentBatchWrite(); @@ -836,7 +836,7 @@ private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTa doc1b["Id"] = 5102; doc1b["Data"] = Guid.NewGuid().ToString(); { - var writer = new DocumentBatchWrite(hashTable); + var writer = hashTable.CreateBatchWrite(); writer.AddDocumentToPut(doc1a); writer.AddDocumentToPut(doc1b); multiTableDocumentBatchWrite.AddBatch(writer); @@ -849,7 +849,7 @@ private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTa doc2b["Id"] = 5202; doc2b["Data"] = Guid.NewGuid().ToString(); { - var writer = new DocumentBatchWrite(hashTable); + var writer = hashTable.CreateBatchWrite(); writer.AddDocumentToPut(doc2a); writer.AddDocumentToPut(doc2b); multiTableDocumentBatchWrite.AddBatch(writer); @@ -861,7 +861,7 @@ private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTa doc3a["Job"] = "Retired"; doc3a["Data"] = Guid.NewGuid().ToString(); { - var writer = new DocumentBatchWrite(hashRangeTable); + var writer = hashRangeTable.CreateBatchWrite(); writer.AddDocumentToPut(doc3a); multiTableDocumentBatchWrite.AddBatch(writer); } @@ -888,7 +888,7 @@ private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTa multiTableDocumentBatchWrite = new MultiTableDocumentBatchWrite(); { - var deleteWriter = new DocumentBatchWrite(hashTable); + var deleteWriter = hashTable.CreateBatchWrite(); deleteWriter.AddItemToDelete(doc1a); deleteWriter.AddItemToDelete(doc1b); deleteWriter.AddItemToDelete(doc2a); @@ -896,14 +896,14 @@ private void TestMultiTableDocumentBatchWrite(Table hashTable, Table hashRangeTa multiTableDocumentBatchWrite.AddBatch(deleteWriter); } { - var deleteWriter = new DocumentBatchWrite(hashRangeTable); + var deleteWriter = hashRangeTable.CreateBatchWrite(); deleteWriter.AddItemToDelete(doc3a); multiTableDocumentBatchWrite.AddBatch(deleteWriter); } multiTableDocumentBatchWrite.Execute(); } - private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRangeTable, DynamoDBEntryConversion conversion) + private void TestMultiTableDocumentTransactWrite(ITable hashTable, ITable hashRangeTable, DynamoDBEntryConversion conversion) { // Test multi-table transactional put var multiTableDocumentTransactWrite = new MultiTableDocumentTransactWrite(); @@ -925,7 +925,7 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang }; { - var transactWrite = new DocumentTransactWrite(hashTable); + var transactWrite = hashTable.CreateTransactWrite(); transactWrite.AddDocumentToPut(hDoc1); transactWrite.AddDocumentToPut(hDoc2); multiTableDocumentTransactWrite.AddTransactionPart(transactWrite); @@ -950,7 +950,7 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang }; { - var transactWrite = new DocumentTransactWrite(hashRangeTable); + var transactWrite = hashRangeTable.CreateTransactWrite(); transactWrite.AddDocumentToPut(hrDoc1); transactWrite.AddDocumentToPut(hrDoc2); multiTableDocumentTransactWrite.AddTransactionPart(transactWrite); @@ -961,12 +961,12 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang { var multiTableDocumentTransactGet = new MultiTableDocumentTransactGet(); - var hTransactGet = new DocumentTransactGet(hashTable); + var hTransactGet = hashTable.CreateTransactGet(); hTransactGet.AddKey(hashKey: 6001); hTransactGet.AddKey(hashKey: 6002); multiTableDocumentTransactGet.AddTransactionPart(hTransactGet); - var hrTransactGet = new DocumentTransactGet(hashRangeTable); + var hrTransactGet = hashRangeTable.CreateTransactGet(); hrTransactGet.AddKey(hashKey: "Alan", rangeKey: 30); hrTransactGet.AddKey(hashKey: "Diane", rangeKey: 40); multiTableDocumentTransactGet.AddTransactionPart(hrTransactGet); @@ -984,7 +984,7 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang multiTableDocumentTransactWrite = new MultiTableDocumentTransactWrite(); { - var transactWrite = new DocumentTransactWrite(hashTable); + var transactWrite = hashTable.CreateTransactWrite(); transactWrite.AddDocumentToUpdate(new Document { ["Price"] = 1001, @@ -999,7 +999,7 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang } { - var transactWrite = new DocumentTransactWrite(hashRangeTable); + var transactWrite = hashRangeTable.CreateTransactWrite(); transactWrite.AddDocumentToUpdate(new Document { ["Score"] = 101, @@ -1018,12 +1018,12 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang { var multiTableDocumentTransactGet = new MultiTableDocumentTransactGet(); - var hTransactGet = new DocumentTransactGet(hashTable); + var hTransactGet = hashTable.CreateTransactGet(); hTransactGet.AddKey(key: new Document { ["Id"] = 6001 }); hTransactGet.AddKey(key: new Document { ["Id"] = 6002 }); multiTableDocumentTransactGet.AddTransactionPart(hTransactGet); - var hrTransactGet = new DocumentTransactGet(hashRangeTable); + var hrTransactGet = hashRangeTable.CreateTransactGet(); hrTransactGet.AddKey(key: new Document { ["Name"] = "Alan", ["Age"] = 30 }); hrTransactGet.AddKey(key: new Document { ["Name"] = "Diane", ["Age"] = 40 }); multiTableDocumentTransactGet.AddTransactionPart(hrTransactGet); @@ -1053,14 +1053,14 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang multiTableDocumentTransactWrite = new MultiTableDocumentTransactWrite(); { - var transactWrite = new DocumentTransactWrite(hashTable); + var transactWrite = hashTable.CreateTransactWrite(); transactWrite.AddKeyToDelete(hashKey: 6001); transactWrite.AddKeyToDelete(key: new Document { ["Id"] = 6002 }); multiTableDocumentTransactWrite.AddTransactionPart(transactWrite); } { - var transactWrite = new DocumentTransactWrite(hashRangeTable); + var transactWrite = hashRangeTable.CreateTransactWrite(); transactWrite.AddKeyToDelete(hashKey: "Alan", rangeKey: 30); transactWrite.AddKeyToDelete(new Document { ["Name"] = "Diane", ["Age"] = 40 }); multiTableDocumentTransactWrite.AddTransactionPart(transactWrite); @@ -1071,12 +1071,12 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang { var multiTableDocumentTransactGet = new MultiTableDocumentTransactGet(); - var hTransactGet = new DocumentTransactGet(hashTable); + var hTransactGet = hashTable.CreateTransactGet(); hTransactGet.AddKey(hashKey: 6001); hTransactGet.AddKey(hashKey: 6002); multiTableDocumentTransactGet.AddTransactionPart(hTransactGet); - var hrTransactGet = new DocumentTransactGet(hashRangeTable); + var hrTransactGet = hashRangeTable.CreateTransactGet(); hrTransactGet.AddKey(hashKey: "Alan", rangeKey: 30); hrTransactGet.AddKey(hashKey: "Diane", rangeKey: 40); multiTableDocumentTransactGet.AddTransactionPart(hrTransactGet); @@ -1087,7 +1087,7 @@ private void TestMultiTableDocumentTransactWrite(Table hashTable, Table hashRang } } - private void TestExpressionsOnDelete(Table hashTable) + private void TestExpressionsOnDelete(ITable hashTable) { Document doc1 = new Document(); doc1["Id"] = 13; @@ -1107,7 +1107,7 @@ private void TestExpressionsOnDelete(Table hashTable) Assert.IsTrue(hashTable.TryDeleteItem(doc1, config)); } - private void TestExpressionsOnTransactWrite(Table hashTable, DynamoDBEntryConversion conversion) + private void TestExpressionsOnTransactWrite(ITable hashTable, DynamoDBEntryConversion conversion) { var doc1 = new Document { @@ -1629,7 +1629,7 @@ private void TestExpressionsOnTransactWrite(Table hashTable, DynamoDBEntryConver } } - private void TestExpressionsOnQuery(Table hashRangeTable) + private void TestExpressionsOnQuery(ITable hashRangeTable) { Document doc1 = new Document(); doc1["Name"] = "Gunnar"; @@ -1668,7 +1668,7 @@ private void TestExpressionsOnQuery(Table hashRangeTable) hashRangeTable.DeleteItem(doc2); } - private void TestExpressionsOnScan(Table hashRangeTable) + private void TestExpressionsOnScan(ITable hashRangeTable) { ClearTable(hashRangeTableName); @@ -1708,7 +1708,7 @@ private void TestExpressionsOnScan(Table hashRangeTable) hashRangeTable.DeleteItem(doc2); } - private void TestExpressionPut(Table hashTable) + private void TestExpressionPut(ITable hashTable) { Document doc = new Document(); @@ -1751,7 +1751,7 @@ private void TestExpressionPut(Table hashTable) hashTable.DeleteItem(doc); } - private void TestExpressionUpdate(Table hashTable) + private void TestExpressionUpdate(ITable hashTable) { Document doc = new Document(); @@ -1810,7 +1810,7 @@ private bool AreValuesEqual(Document docA, Document docB, DynamoDBEntryConversio return true; return docA.Equals(docB); } - private void LoadTables(DynamoDBEntryConversion conversion, out Table hashTable, out Table hashRangeTable, out Table numericHashRangeTable) + private void LoadTables(DynamoDBEntryConversion conversion, out ITable hashTable, out ITable hashRangeTable, out ITable numericHashRangeTable) { TableCache.Clear(); diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/Extensions.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/Extensions.cs index adc14527f9af..b40a8b6b1492 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/Extensions.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/Extensions.cs @@ -28,7 +28,7 @@ public static Dictionary MakeKey(this Table table, Docum public static Dictionary MakeKey(this DynamoDBContext context, T item) { var doc = context.ToDocument(item); - var table = context.GetTargetTable(); + var table = context.GetTargetTable() as Table; var key = table.MakeKey(doc); return key; } diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/JSONTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/JSONTests.cs index a4d4b23dec6a..f76b987ec576 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/JSONTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/JSONTests.cs @@ -86,9 +86,9 @@ private void TestPutGet() // Clear tables CleanupTables(); - Table hashTable; - Table hashRangeTable; - Table numericHashRangeTable; + ITable hashTable; + ITable hashRangeTable; + ITable numericHashRangeTable; // Load tables using provided conversion schema LoadTables(DynamoDBEntryConversion.V2, out hashTable, out hashRangeTable, out numericHashRangeTable); diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/TTLTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/TTLTests.cs index f92b023140a2..f62d71de4264 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/TTLTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/TTLTests.cs @@ -77,7 +77,7 @@ public void TestStoreAsEpoch() ApproximatelyEqual(EpochDate, docV2["NonEpochDate1"].AsDateTime()); ApproximatelyEqual(EpochDate, docV2["NonEpochDate1"].AsDateTime()); - var epochTable = Context.GetTargetTable(); + var epochTable = Context.GetTargetTable() as Table; // Do an explicit cast since we want to access internal methods. var epochAttributes = epochTable.GetStoreAsEpoch().ToList(); Assert.AreNotEqual(0, epochAttributes.Count); @@ -137,7 +137,7 @@ public void TestStoreAsAnnotatedEpoch() ApproximatelyEqual(EpochDate, docV2["NonEpochDate1"].AsDateTime()); ApproximatelyEqual(EpochDate, docV2["NonEpochDate1"].AsDateTime()); - var epochTable = Context.GetTargetTable(); + var epochTable = Context.GetTargetTable() as Table; var epochAttributes = epochTable.GetStoreAsEpoch().ToList(); Assert.AreNotEqual(0, epochAttributes.Count); @@ -148,7 +148,7 @@ public void TestStoreAsAnnotatedEpoch() Assert.IsNotNull(epochMap["NonEpochDate2"].S); } - public void TestStoreAsEpoch(Table hashRangeTable, Table numericHashRangeTable) + public void TestStoreAsEpoch(ITable hashRangeTable, ITable numericHashRangeTable) { // verify conversions var e1 = DateTimeToEpochSeconds((Primitive) EpochDate, "test") as Primitive; @@ -167,7 +167,7 @@ public void TestStoreAsEpoch(Table hashRangeTable, Table numericHashRangeTable) AttributesToStoreAsEpoch = new List { "CreationTime", "EpochDate2" } }; #pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors - var epochTable = Table.LoadTable(Client, config); + var epochTable = Table.LoadTable(Client, config) as Table; // Do an explicit cast since we want to access internal methods. #pragma warning restore CS0618 // Re-enable the warning CollectionAssert.AreEqual(config.AttributesToStoreAsEpoch, epochTable.GetStoreAsEpoch().ToList()); @@ -322,7 +322,7 @@ private static Document CreateTestDocument() doc["NonEpochDate"] = EpochDate; return doc; } - private static void TestWrittenData(Primitive hash, Primitive range, Table hashRangeTable, Table epochTable, bool checkForConditionalUpdate = false) + private static void TestWrittenData(Primitive hash, Primitive range, ITable hashRangeTable, ITable epochTable, bool checkForConditionalUpdate = false) { if (hashRangeTable != null) { 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..879324931498 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchGetTests.cs @@ -0,0 +1,155 @@ +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 mockTable = new Mock(); + mockTable.Setup(x => x.CreateBatchGet()).Returns(CreateDocumentBatchGetMock(dummyResults)); + var table = mockTable.Object; + + var docBatchGet = table.CreateBatchGet(); + + 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; + } + } +} 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..5f1945d47d99 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentBatchWriteTests.cs @@ -0,0 +1,118 @@ +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 mockTable = new Mock(); + mockTable.Setup(x => x.CreateBatchWrite()).Returns(CreateDocumentBatchWriteMock(itemsToPut, inMemoryTable)); + var table = mockTable.Object; + + var batchWrite = table.CreateBatchWrite(); + + 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; + } + } +} 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..e5c5ab044ad6 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentSearchTests.cs @@ -0,0 +1,72 @@ +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_DocumentScan() + { + var mockTable = new Mock(); + mockTable + .Setup(x => x.Scan(It.IsAny())) + .Returns(CreateSearchMock(new List() + { + new Document(){ {"id", 1}, {"name", "Bob"} }, + new Document(){ {"id", 2}, {"name", "Tom"} } + })); + var table = mockTable.Object; + + var search = table.Scan((ScanOperationConfig)null); + + 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()); + } + + [TestMethod] + public void TestMockability_DocumentQuery() + { + var mockTable = new Mock(); + mockTable + .Setup(x => x.Query(It.IsAny())) + .Returns(CreateSearchMock(new List() + { + new Document(){ {"id", 1}, {"name", "Bob"} }, + new Document(){ {"id", 2}, {"name", "Tom"} } + })); + var table = mockTable.Object; + + var search = table.Query((QueryOperationConfig)null); + + 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; + } + } +} 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..1612a4e32d67 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactGetTests.cs @@ -0,0 +1,122 @@ +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 mockTable = new Mock(); + mockTable.Setup(x => x.CreateTransactGet()).Returns(CreateDocumentTransactGetMock(dummyResults)); + var table = mockTable.Object; + + var addressTransactGet = table.CreateTransactGet(); + + 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; + } + } +} 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..58fd1392f1c6 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/DocumentTransactWriteTests.cs @@ -0,0 +1,117 @@ +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 mockTable = new Mock(); + mockTable.Setup(x => x.CreateTransactWrite()).Returns(CreateDocumentTransactWriteMock(itemsToPut, inMemoryTable)); + var table = mockTable.Object; + + var docTransactWrite = table.CreateTransactWrite(); + + 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 c5487d5a6345792b50e72c338429e8bb32dc9dc4 Mon Sep 17 00:00:00 2001 From: Phil Asmar Date: Thu, 22 Aug 2024 19:22:12 -0400 Subject: [PATCH 7/7] fix: fix failing tests due to build errors --- .../DynamoDB/DocumentTests.cs | 28 +++++++++---------- .../IntegrationTests/DynamoDB/JSONTests.cs | 4 +-- .../IntegrationTests/DynamoDBTruncateError.cs | 4 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DocumentTests.cs b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DocumentTests.cs index 746a3374013b..86bdb1808e31 100644 --- a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DocumentTests.cs +++ b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DocumentTests.cs @@ -26,8 +26,8 @@ public async Task TestTableOperations() // Clear tables await SharedTestFixture.CleanupTables(); - Table hashTable; - Table hashRangeTable; + ITable hashTable; + ITable hashRangeTable; // Load tables using provided conversion schema LoadTables(conversion, out hashTable, out hashRangeTable); @@ -64,7 +64,7 @@ public async Task TestTableOperations() } } - private async Task TestPagination(Table hashRangeTable) + private async Task TestPagination(ITable hashRangeTable) { var itemCount = 10; var batchWrite = hashRangeTable.CreateBatchWrite(); @@ -136,7 +136,7 @@ private async Task TestPagination(Table hashRangeTable) } } - private static async Task VerifyPagination(Search search, List tokens) + private static async Task VerifyPagination(ISearch search, List tokens) { int count = 0; do @@ -156,7 +156,7 @@ private static async Task VerifyPagination(Search search, List toke return count; } - private async Task TestEmptyCollections(Table hashTable) + private async Task TestEmptyCollections(ITable hashTable) { Document doc = new Document(); doc["Id"] = 1; @@ -179,7 +179,7 @@ private async Task TestEmptyCollections(Table hashTable) Assert.Empty(listEntry.AsDynamoDBList().Entries); } - private async Task TestHashTable(Table hashTable, DynamoDBEntryConversion conversion) + private async Task TestHashTable(ITable hashTable, DynamoDBEntryConversion conversion) { // Put an item Document doc = new Document(); @@ -343,7 +343,7 @@ private async Task TestHashTable(Table hashTable, DynamoDBEntryConversion conver items = await hashTable.Scan(new ScanFilter()).GetRemainingAsync(); Assert.Empty(items); } - private async Task TestHashRangeTable(Table hashRangeTable, DynamoDBEntryConversion conversion) + private async Task TestHashRangeTable(ITable hashRangeTable, DynamoDBEntryConversion conversion) { // Put an item Document doc1 = new Document(); @@ -556,7 +556,7 @@ private async Task TestHashRangeTable(Table hashRangeTable, DynamoDBEntryConvers }).GetRemainingAsync(); Assert.Single(items); } - private async Task TestLargeBatchOperations(Table hashTable) + private async Task TestLargeBatchOperations(ITable hashTable) { int itemCount = 30; int itemSize = 40 * 1024; @@ -604,7 +604,7 @@ private async Task TestLargeBatchOperations(Table hashTable) Assert.Empty(items); } - private async Task TestExpressionsOnDelete(Table hashTable) + private async Task TestExpressionsOnDelete(ITable hashTable) { Document doc1 = new Document(); doc1["Id"] = 13; @@ -624,7 +624,7 @@ private async Task TestExpressionsOnDelete(Table hashTable) await hashTable.DeleteItemAsync(doc1, config); } - private async Task TestExpressionsOnQuery(Table hashRangeTable) + private async Task TestExpressionsOnQuery(ITable hashRangeTable) { Document doc1 = new Document(); doc1["Name"] = "Gunnar"; @@ -663,7 +663,7 @@ private async Task TestExpressionsOnQuery(Table hashRangeTable) await hashRangeTable.DeleteItemAsync(doc2); } - private async Task TestExpressionsOnScan(Table hashRangeTable) + private async Task TestExpressionsOnScan(ITable hashRangeTable) { await SharedTestFixture.ClearTable(SharedTestFixture.hashRangeTableName); @@ -703,7 +703,7 @@ private async Task TestExpressionsOnScan(Table hashRangeTable) await hashRangeTable.DeleteItemAsync(doc2); } - private async Task TestExpressionPut(Table hashTable) + private async Task TestExpressionPut(ITable hashTable) { Document doc = new Document(); @@ -746,7 +746,7 @@ private async Task TestExpressionPut(Table hashTable) await hashTable.DeleteItemAsync(doc); } - private async Task TestExpressionUpdate(Table hashTable) + private async Task TestExpressionUpdate(ITable hashTable) { Document doc = new Document(); @@ -805,7 +805,7 @@ private bool AreValuesEqual(Document docA, Document docB, DynamoDBEntryConversio return true; return docA.Equals(docB); } - private void LoadTables(DynamoDBEntryConversion conversion, out Table hashTable, out Table hashRangeTable) + private void LoadTables(DynamoDBEntryConversion conversion, out ITable hashTable, out ITable hashRangeTable) { SharedTestFixture.TableCache.Clear(); diff --git a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/JSONTests.cs b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/JSONTests.cs index e556fa6eacd6..d94000824d32 100644 --- a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/JSONTests.cs +++ b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/JSONTests.cs @@ -49,8 +49,8 @@ private async Task TestPutGet() // Clear tables await SharedTestFixture.CleanupTables(); - Table hashTable; - Table hashRangeTable; + ITable hashTable; + ITable hashRangeTable; // Load tables using provided conversion schema LoadTables(DynamoDBEntryConversion.V2, out hashTable, out hashRangeTable); diff --git a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDBTruncateError.cs b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDBTruncateError.cs index 57f12ca3f7ee..c134060a2574 100644 --- a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDBTruncateError.cs +++ b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDBTruncateError.cs @@ -369,7 +369,7 @@ private async Task DeleteTable(IAmazonDynamoDB dynamoDBClient, string tableName) await dynamoDBClient.DeleteTableAsync(tableName); } - private static async Task InsertData(Table table, string id, string body) + private static async Task InsertData(ITable table, string id, string body) { await table.PutItemAsync(new Document(new Dictionary { @@ -378,7 +378,7 @@ await table.PutItemAsync(new Document(new Dictionary })); } - private async Task ReadData(Table table, string id) + private async Task ReadData(ITable table, string id) { Document doc = await table.GetItemAsync(new Primitive(id));