From 1c1d7b52279905b995bfc7e6fab6edebf1ed7abc Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Mon, 5 Aug 2024 11:48:27 -0400 Subject: [PATCH 1/3] fix: Honor an OverrideTableName and DisableFetchingTableMetadata when specified on a DynamoDBOperationConfig, instead of just on the DynamoDBContextConfig --- .../DynamoDBv2/Custom/DataModel/Configs.cs | 34 ++++++++------ .../UnitTests/Custom/DynamoDBTests.cs | 46 +++++++++++++++++-- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs index 9eb5dad92d64..f75bf9220351 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs @@ -48,8 +48,8 @@ public interface IPropertyConverter } /// - /// Configuration object for setting options on the DynamoDBContext. - /// and individual operations. + /// Configuration object for setting options on the that + /// will apply to all operations that use the context object. /// #if NET8_0_OR_GREATER [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] @@ -81,6 +81,16 @@ public DynamoDBContextConfig() /// public bool? SkipVersionCheck { get; set; } + /// + /// Indicates which DynamoDB table to use. This overrides the table specified + /// by the on the .NET objects that you're saving or loading. + /// + /// + /// If you specify this on , then it will apply to all + /// objects/tables used with that object unless overriden by an operation-specific config. + /// + public string OverrideTableName { get; set; } + /// /// Property that directs DynamoDBContext to prefix all table names /// with a specific string. @@ -152,12 +162,6 @@ public DynamoDBContextConfig() #endif public class DynamoDBOperationConfig : DynamoDBContextConfig { - /// - /// Property that indicates the table to save an object to overriding the DynamoDBTable attribute - /// declared for the type. - /// - public string OverrideTableName { get; set; } - /// /// Property that indicates a query should traverse the index backward. /// If the property is false (or not set), traversal shall be forward. @@ -346,25 +350,29 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte if (contextConfig == null) contextConfig = _emptyContextConfig; + // These properties can be set at either the operation or context levels bool consistentRead = operationConfig.ConsistentRead ?? contextConfig.ConsistentRead ?? false; bool skipVersionCheck = operationConfig.SkipVersionCheck ?? contextConfig.SkipVersionCheck ?? false; bool ignoreNullValues = operationConfig.IgnoreNullValues ?? contextConfig.IgnoreNullValues ?? false; - bool disableFetchingTableMetadata = contextConfig.DisableFetchingTableMetadata ?? false; + bool disableFetchingTableMetadata = operationConfig.DisableFetchingTableMetadata ?? contextConfig.DisableFetchingTableMetadata ?? false; bool retrieveDateTimeInUtc = operationConfig.RetrieveDateTimeInUtc ?? contextConfig.RetrieveDateTimeInUtc ?? false; - bool isEmptyStringValueEnabled = operationConfig.IsEmptyStringValueEnabled ?? contextConfig.IsEmptyStringValueEnabled ?? false; + DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion; + MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default; + string overrideTableName = - !string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : string.Empty; + !string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : + !string.IsNullOrEmpty(contextConfig.OverrideTableName) ? contextConfig.OverrideTableName : string.Empty; string tableNamePrefix = !string.IsNullOrEmpty(operationConfig.TableNamePrefix) ? operationConfig.TableNamePrefix : !string.IsNullOrEmpty(contextConfig.TableNamePrefix) ? contextConfig.TableNamePrefix : string.Empty; + + // These properties can only be set at the operation level, and are related to querying or scanning bool backwardQuery = operationConfig.BackwardQuery ?? false; string indexName = !string.IsNullOrEmpty(operationConfig.IndexName) ? operationConfig.IndexName : DefaultIndexName; List queryFilter = operationConfig.QueryFilter ?? new List(); ConditionalOperatorValues conditionalOperator = operationConfig.ConditionalOperator; - DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion; - MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default; ConsistentRead = consistentRead; SkipVersionCheck = skipVersionCheck; diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs index d65de7d00f52..0a573ee7ac2a 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs @@ -451,16 +451,17 @@ public void DisableFetchingTableMetadata_QueryWithMissingHashKey_ThrowsException [TestCategory("DynamoDBv2")] public void DisableFetchingTableMetadata_QueryWithMissingRangeKey_ThrowsException() { - var config = new DynamoDBContextConfig() + // For variety, use the operation-level override + var config = new DynamoDBOperationConfig() { DisableFetchingTableMetadata = true }; - var context = new DynamoDBContext(new Mock().Object, config); + var context = new DynamoDBContext(new Mock().Object); // This is the table's range key, which is not attributed Assert.ThrowsException(() => - context.Query("123", QueryOperator.GreaterThan, 5)); + context.Query("123", QueryOperator.GreaterThan, 5, config)); // This is a GSI's range key, which is not attributed Assert.ThrowsException(() => @@ -754,5 +755,44 @@ public class DataModelWithMixedAccessibility public string PublicAccessToProtected => _protected; } + + /// + /// Verifies that specifing an TableName on the operation-level config overrides + /// the table name from the data model + /// + [TestMethod] + public void OperationConfig_CanOverrideTableName() + { + var client = new Mock(); + client.Setup(client => client.DescribeTable(It.IsAny())) + .Returns(new DescribeTableResponse { Table = new TableDescription + { + KeySchema = new List + { + new KeySchemaElement("Name", KeyType.HASH), + new KeySchemaElement("Age", KeyType.RANGE) + }, + AttributeDefinitions = new List() + { + new AttributeDefinition("Name", ScalarAttributeType.S), + new AttributeDefinition("Age", ScalarAttributeType.S) + } + }}); + client.Setup(client => client.Query(It.IsAny())).Returns(new QueryResponse { Items = new() }); + + var config = new DynamoDBOperationConfig + { + OverrideTableName = "OverrideTableName" + }; + + var context = new DynamoDBContext(client.Object, config); + + var query = context.Query("123", config); + var objects = query.ToList(); + + client.Verify(client => client.DescribeTable(It.Is(request => request.TableName == "OverrideTableName")), Times.Once()); + client.Verify(client => client.Query(It.Is(request => request.TableName == "OverrideTableName")), Times.Once()); + client.VerifyNoOtherCalls(); + } } } From e11b6e50c331bfada0579ec0acd84ce3cf171c04 Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Fri, 9 Aug 2024 20:16:41 -0400 Subject: [PATCH 2/3] Separate DynamoDBContextConfig and DynamoDBOperationConfig, clean up documentation --- .../DynamoDBv2/Custom/DataModel/Configs.cs | 170 ++++++++++++++---- 1 file changed, 133 insertions(+), 37 deletions(-) diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs index f75bf9220351..50d2a43b7514 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs @@ -13,13 +13,10 @@ * permissions and limitations under the License. */ -using System; -using System.Collections.Generic; - using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; -using System.Globalization; using Amazon.Util; +using System; +using System.Collections.Generic; namespace Amazon.DynamoDBv2.DataModel { @@ -69,30 +66,24 @@ public DynamoDBContextConfig() } /// - /// Property that directs DynamoDBContext to use consistent reads. + /// Property that directs to use consistent reads. /// If property is not set, behavior defaults to non-consistent reads. /// + /// + /// Refer to the + /// Read Consistency topic in the DynamoDB Developer Guide for more information. + /// public bool? ConsistentRead { get; set; } /// - /// Property that directs DynamoDBContext to skip version checks + /// Property that directs to skip version checks /// when saving or deleting an object with a version attribute. /// If property is not set, version checks are performed. /// public bool? SkipVersionCheck { get; set; } /// - /// Indicates which DynamoDB table to use. This overrides the table specified - /// by the on the .NET objects that you're saving or loading. - /// - /// - /// If you specify this on , then it will apply to all - /// objects/tables used with that object unless overriden by an operation-specific config. - /// - public string OverrideTableName { get; set; } - - /// - /// Property that directs DynamoDBContext to prefix all table names + /// Property that directs to prefix all table names /// with a specific string. /// If property is null or empty, no prefix is used and default /// table names are used. @@ -112,7 +103,7 @@ public DynamoDBContextConfig() public MetadataCachingMode? MetadataCachingMode { get; set; } /// - /// Property that directs DynamoDBContext to ignore null values + /// Property that directs to ignore null values /// on attributes during a Save operation. /// If the property is false (or not set), null values will be /// interpreted as directives to delete the specific attribute. @@ -120,7 +111,7 @@ public DynamoDBContextConfig() public bool? IgnoreNullValues { get; set; } /// - /// Property that directs DynamoDBContext to enable empty string values + /// Property that directs to enable empty string values /// on attributes during a Save operation. /// If the property is false (or not set), empty string values will be /// interpreted as null values. @@ -148,7 +139,9 @@ public DynamoDBContextConfig() /// /// If true, all properties are retrieved in UTC timezone while reading data from DynamoDB. Else, the local timezone is used. /// - /// This setting is only applicable to the high-level library. Service calls made via will always return attributes in UTC. + /// This setting is only applicable to the high-level library. + /// Service calls made via will always return + /// attributes in UTC. public bool? RetrieveDateTimeInUtc { get; set; } } @@ -160,11 +153,101 @@ public DynamoDBContextConfig() #if NET8_0_OR_GREATER [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] #endif - public class DynamoDBOperationConfig : DynamoDBContextConfig + public class DynamoDBOperationConfig { /// - /// Property that indicates a query should traverse the index backward. - /// If the property is false (or not set), traversal shall be forward. + /// Property that directs to use consistent reads. + /// If property is not set, behavior defaults to non-consistent reads. + /// + /// + /// Refer to the + /// Read Consistency topic in the DynamoDB Developer Guide for more information. + /// + public bool? ConsistentRead { get; set; } + + /// + /// Property that directs to skip version checks + /// when saving or deleting an object with a version attribute. + /// If property is not set, version checks are performed. + /// + public bool? SkipVersionCheck { get; set; } + + /// + /// Indicates which DynamoDB table to use. This overrides the table specified + /// by the on the .NET objects that you're saving or loading. + /// + /// + /// If you want to specify this globally instead of for each operation, you can use + /// the or collections + /// on . + /// + public string OverrideTableName { get; set; } + + /// + /// Property that directs to prefix all table names + /// with a specific string. + /// If property is null or empty, no prefix is used and default + /// table names are used. + /// + public string TableNamePrefix { get; set; } + + /// + /// The object persistence model API relies on an internal cache of the DynamoDB table's metadata to construct and validate + /// requests. This controls how the cache key is derived, which influences when the SDK will call + /// IAmazonDynamoDB.DescribeTable(string) internally to populate the cache. + /// + /// + /// For the cache key will be a combination of the table name, credentials, region and service URL. + /// For the cache key will only consist of the table name. This reduces cache misses in contexts + /// where you are accessing tables with identical structure but using different credentials or endpoints (such as a multi-tenant application). + /// + public MetadataCachingMode? MetadataCachingMode { get; set; } + + /// + /// Property that directs to ignore null values + /// on attributes during a Save operation. + /// If the property is false (or not set), null values will be + /// interpreted as directives to delete the specific attribute. + /// + public bool? IgnoreNullValues { get; set; } + + /// + /// Property that directs to enable empty string values + /// on attributes during a Save operation. + /// If the property is false (or not set), empty string values will be + /// interpreted as null values. + /// + public bool? IsEmptyStringValueEnabled { get; set; } + + /// + /// Conversion specification which controls how conversion between + /// .NET and DynamoDB types happens. + /// + public DynamoDBEntryConversion Conversion { get; set; } + + /// + /// If true disables fetching table metadata automatically from DynamoDB. Table metadata must be + /// defined by attributes and/or in . + /// + /// + /// Setting this to true can avoid latency and thread starvation due to blocking asynchronous + /// IAmazonDynamoDB.DescribeTable(string) calls that are used to populate the SDK's cache of + /// table metadata. It requires that the table's index schema be accurately described via the above methods, + /// otherwise exceptions may be thrown and/or the results of certain DynamoDB operations may change. + /// + public bool? DisableFetchingTableMetadata { get; set; } + + /// + /// If true, all properties are retrieved in UTC timezone while reading data from DynamoDB. Else, the local timezone is used. + /// + /// This setting is only applicable to the high-level library. + /// Service calls made via will always return + /// attributes in UTC. + public bool? RetrieveDateTimeInUtc { get; set; } + + /// + /// Indicates whether a query should traverse the index backwards in descending order by range key value. + /// If the property is false (or not set), traversal shall be in ascending order. /// public bool? BackwardQuery { get; set; } @@ -175,20 +258,31 @@ public class DynamoDBOperationConfig : DynamoDBContextConfig public string IndexName { get; set; } /// - /// A logical operator to apply to the filter conditions: - /// AND - If all of the conditions evaluate to true, then the entire filter evaluates to true. - /// OR - If at least one of the conditions evaluate to true, then the entire filter evaluates to true. - /// - /// Default value is AND. + /// The logical operator to apply to the filter conditions. /// + /// + /// + /// + /// + /// If all of the conditions evaluate to true, then the entire filter evaluates to true. + /// + /// + /// + /// If at least one of the conditions evaluate to true, then the entire filter evaluates to true. + /// + /// + /// The default value is . + /// public ConditionalOperatorValues ConditionalOperator { get; set; } /// - /// Query filter for the Query operation operation. Evaluates the query results and returns only + /// Query filter for the Query operation. Evaluates the query results and returns only /// the matching values. If you specify more than one condition, then by default all of the - /// conditions must evaluate to true. To match only some conditions, set ConditionalOperator to Or. - /// Note: Conditions must be against non-key properties. + /// conditions must evaluate to true. To match only some conditions, set to . /// + /// + /// Note: Conditions must be against non-key properties. + /// public List QueryFilter { get; set; } /// @@ -199,7 +293,9 @@ public DynamoDBOperationConfig() QueryFilter = new List(); } - // Checks if the IndexName is set on the config + /// + /// Checks if the IndexName is set on the config + /// internal bool IsIndexOperation { get { return !string.IsNullOrEmpty(IndexName); } } } @@ -360,14 +456,14 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion; MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default; - string overrideTableName = - !string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : - !string.IsNullOrEmpty(contextConfig.OverrideTableName) ? contextConfig.OverrideTableName : string.Empty; string tableNamePrefix = !string.IsNullOrEmpty(operationConfig.TableNamePrefix) ? operationConfig.TableNamePrefix : !string.IsNullOrEmpty(contextConfig.TableNamePrefix) ? contextConfig.TableNamePrefix : string.Empty; - // These properties can only be set at the operation level, and are related to querying or scanning + // These properties can only be set at the operation level, most are related to querying or scanning. + // We don't support overriding the table name at the context level, since a context object can be used with multiple tables. + string overrideTableName = + !string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : string.Empty; bool backwardQuery = operationConfig.BackwardQuery ?? false; string indexName = !string.IsNullOrEmpty(operationConfig.IndexName) ? operationConfig.IndexName : DefaultIndexName; From cd2e44a5cf5c50b0d60570f1f878d6c3d20ebf0a Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Fri, 9 Aug 2024 22:10:24 -0400 Subject: [PATCH 3/3] Remove table caching properties from operation specific configs. --- .../Custom/DataModel/BaseOperationConfig.cs | 26 ----------- .../DynamoDBv2/Custom/DataModel/Configs.cs | 37 +++------------ .../DataModelOperationSpecificConfigTests.cs | 30 ++++++------ .../UnitTests/Custom/DynamoDBTests.cs | 46 ++----------------- 4 files changed, 25 insertions(+), 114 deletions(-) diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs index e8a5a5ea8759..73f976824695 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs @@ -41,30 +41,6 @@ public abstract class BaseOperationConfig /// public string TableNamePrefix { get; set; } - /// - /// The object persistence model API relies on an internal cache of the DynamoDB table's metadata to - /// construct and validate requests. This controls how the cache key is derived, which influences - /// when the SDK will call DescribeTable internally to populate the cache. - /// - /// - /// For the cache key will be a combination of the table name, credentials, region and service URL. - /// For the cache key will only consist of the table name. This reduces cache misses in contexts - /// where you are accessing tables with identical structure but using different credentials or endpoints (such as a multi-tenant application). - /// - public MetadataCachingMode? MetadataCachingMode { get; set; } - - /// - /// If true disables fetching table metadata automatically from DynamoDB. Table metadata must be - /// defined by attributes and/or in . - /// - /// - /// Setting this to true can avoid latency and thread starvation due to blocking asynchronous - /// DescribeTable calls that are used to populate the SDK's cache of table metadata. - /// It requires that the table's index schema be accurately described via the above methods, - /// otherwise exceptions may be thrown and/or the results of certain DynamoDB operations may change. - /// - public bool? DisableFetchingTableMetadata { get; set; } - /// /// Specification which controls the conversion between .NET and DynamoDB types. /// @@ -91,8 +67,6 @@ internal virtual DynamoDBOperationConfig ToDynamoDBOperationConfig() { OverrideTableName = OverrideTableName, TableNamePrefix = TableNamePrefix, - MetadataCachingMode = MetadataCachingMode, - DisableFetchingTableMetadata = DisableFetchingTableMetadata, Conversion = Conversion, IsEmptyStringValueEnabled = IsEmptyStringValueEnabled }; diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs index 50d2a43b7514..da8406801bc1 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs @@ -191,18 +191,6 @@ public class DynamoDBOperationConfig /// public string TableNamePrefix { get; set; } - /// - /// The object persistence model API relies on an internal cache of the DynamoDB table's metadata to construct and validate - /// requests. This controls how the cache key is derived, which influences when the SDK will call - /// IAmazonDynamoDB.DescribeTable(string) internally to populate the cache. - /// - /// - /// For the cache key will be a combination of the table name, credentials, region and service URL. - /// For the cache key will only consist of the table name. This reduces cache misses in contexts - /// where you are accessing tables with identical structure but using different credentials or endpoints (such as a multi-tenant application). - /// - public MetadataCachingMode? MetadataCachingMode { get; set; } - /// /// Property that directs to ignore null values /// on attributes during a Save operation. @@ -225,18 +213,6 @@ public class DynamoDBOperationConfig /// public DynamoDBEntryConversion Conversion { get; set; } - /// - /// If true disables fetching table metadata automatically from DynamoDB. Table metadata must be - /// defined by attributes and/or in . - /// - /// - /// Setting this to true can avoid latency and thread starvation due to blocking asynchronous - /// IAmazonDynamoDB.DescribeTable(string) calls that are used to populate the SDK's cache of - /// table metadata. It requires that the table's index schema be accurately described via the above methods, - /// otherwise exceptions may be thrown and/or the results of certain DynamoDB operations may change. - /// - public bool? DisableFetchingTableMetadata { get; set; } - /// /// If true, all properties are retrieved in UTC timezone while reading data from DynamoDB. Else, the local timezone is used. /// @@ -425,8 +401,7 @@ internal class DynamoDBFlatConfig IndexName = null, ConditionalOperator = ConditionalOperatorValues.And, Conversion = null, - IsEmptyStringValueEnabled = null, - MetadataCachingMode = null + IsEmptyStringValueEnabled = null }; private static DynamoDBContextConfig _emptyContextConfig = new DynamoDBContextConfig { @@ -450,20 +425,22 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte bool consistentRead = operationConfig.ConsistentRead ?? contextConfig.ConsistentRead ?? false; bool skipVersionCheck = operationConfig.SkipVersionCheck ?? contextConfig.SkipVersionCheck ?? false; bool ignoreNullValues = operationConfig.IgnoreNullValues ?? contextConfig.IgnoreNullValues ?? false; - bool disableFetchingTableMetadata = operationConfig.DisableFetchingTableMetadata ?? contextConfig.DisableFetchingTableMetadata ?? false; bool retrieveDateTimeInUtc = operationConfig.RetrieveDateTimeInUtc ?? contextConfig.RetrieveDateTimeInUtc ?? false; bool isEmptyStringValueEnabled = operationConfig.IsEmptyStringValueEnabled ?? contextConfig.IsEmptyStringValueEnabled ?? false; DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion; - MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default; - string tableNamePrefix = !string.IsNullOrEmpty(operationConfig.TableNamePrefix) ? operationConfig.TableNamePrefix : !string.IsNullOrEmpty(contextConfig.TableNamePrefix) ? contextConfig.TableNamePrefix : string.Empty; - // These properties can only be set at the operation level, most are related to querying or scanning. + // These properties can only be set at the operation level + bool disableFetchingTableMetadata = contextConfig.DisableFetchingTableMetadata ?? false; + MetadataCachingMode metadataCachingMode = contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default; + // We don't support overriding the table name at the context level, since a context object can be used with multiple tables. string overrideTableName = !string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : string.Empty; + + // The rest are related to querying or scanning, so only operation level bool backwardQuery = operationConfig.BackwardQuery ?? false; string indexName = !string.IsNullOrEmpty(operationConfig.IndexName) ? operationConfig.IndexName : DefaultIndexName; diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs index 583ca879b8f9..550c96a31a08 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs @@ -21,7 +21,7 @@ public void BaseOperationConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(6, typeof(BaseOperationConfig).GetProperties().Length); + Assert.AreEqual(4, typeof(BaseOperationConfig).GetProperties().Length); } [TestMethod] @@ -29,7 +29,7 @@ public void BatchGetConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(8, typeof(BatchGetConfig).GetProperties().Length); + Assert.AreEqual(6, typeof(BatchGetConfig).GetProperties().Length); } [TestMethod] @@ -62,7 +62,7 @@ public void BatchWriteConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(8, typeof(BatchWriteConfig).GetProperties().Length); + Assert.AreEqual(6, typeof(BatchWriteConfig).GetProperties().Length); } [TestMethod] @@ -95,7 +95,7 @@ public void TransactGetConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(TransactGetConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(TransactGetConfig).GetProperties().Length); } [TestMethod] @@ -128,7 +128,7 @@ public void TransactWriteConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(TransactWriteConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(TransactWriteConfig).GetProperties().Length); } [TestMethod] @@ -161,7 +161,7 @@ public void QueryConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(12, typeof(QueryConfig).GetProperties().Length); + Assert.AreEqual(10, typeof(QueryConfig).GetProperties().Length); } [TestMethod] @@ -193,7 +193,7 @@ public void FromQueryConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(FromQueryConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(FromQueryConfig).GetProperties().Length); } [TestMethod] @@ -230,7 +230,7 @@ public void ScanConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(11, typeof(ScanConfig).GetProperties().Length); + Assert.AreEqual(9, typeof(ScanConfig).GetProperties().Length); } [TestMethod] @@ -262,7 +262,7 @@ public void FromScanConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(FromScanConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(FromScanConfig).GetProperties().Length); } [TestMethod] @@ -294,7 +294,7 @@ public void DeleteConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(DeleteConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(DeleteConfig).GetProperties().Length); } [TestMethod] @@ -325,7 +325,7 @@ public void SaveConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(8, typeof(SaveConfig).GetProperties().Length); + Assert.AreEqual(6, typeof(SaveConfig).GetProperties().Length); } [TestMethod] @@ -356,7 +356,7 @@ public void LoadConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(8, typeof(LoadConfig).GetProperties().Length); + Assert.AreEqual(6, typeof(LoadConfig).GetProperties().Length); } [TestMethod] @@ -387,7 +387,7 @@ public void ToDocumentConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(ToDocumentConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(ToDocumentConfig).GetProperties().Length); } [TestMethod] @@ -395,7 +395,7 @@ public void FromDocumentConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(7, typeof(FromDocumentConfig).GetProperties().Length); + Assert.AreEqual(5, typeof(FromDocumentConfig).GetProperties().Length); } [TestMethod] @@ -403,7 +403,7 @@ public void GetTargetTableConfig() { // If this fails because you've added a property, be sure to add it to // `ToDynamoDBOperationConfig` before updating this unit test - Assert.AreEqual(6, typeof(GetTargetTableConfig).GetProperties().Length); + Assert.AreEqual(4, typeof(GetTargetTableConfig).GetProperties().Length); } [DynamoDBTable("TableName")] diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs index 0a573ee7ac2a..d65de7d00f52 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs @@ -451,17 +451,16 @@ public void DisableFetchingTableMetadata_QueryWithMissingHashKey_ThrowsException [TestCategory("DynamoDBv2")] public void DisableFetchingTableMetadata_QueryWithMissingRangeKey_ThrowsException() { - // For variety, use the operation-level override - var config = new DynamoDBOperationConfig() + var config = new DynamoDBContextConfig() { DisableFetchingTableMetadata = true }; - var context = new DynamoDBContext(new Mock().Object); + var context = new DynamoDBContext(new Mock().Object, config); // This is the table's range key, which is not attributed Assert.ThrowsException(() => - context.Query("123", QueryOperator.GreaterThan, 5, config)); + context.Query("123", QueryOperator.GreaterThan, 5)); // This is a GSI's range key, which is not attributed Assert.ThrowsException(() => @@ -755,44 +754,5 @@ public class DataModelWithMixedAccessibility public string PublicAccessToProtected => _protected; } - - /// - /// Verifies that specifing an TableName on the operation-level config overrides - /// the table name from the data model - /// - [TestMethod] - public void OperationConfig_CanOverrideTableName() - { - var client = new Mock(); - client.Setup(client => client.DescribeTable(It.IsAny())) - .Returns(new DescribeTableResponse { Table = new TableDescription - { - KeySchema = new List - { - new KeySchemaElement("Name", KeyType.HASH), - new KeySchemaElement("Age", KeyType.RANGE) - }, - AttributeDefinitions = new List() - { - new AttributeDefinition("Name", ScalarAttributeType.S), - new AttributeDefinition("Age", ScalarAttributeType.S) - } - }}); - client.Setup(client => client.Query(It.IsAny())).Returns(new QueryResponse { Items = new() }); - - var config = new DynamoDBOperationConfig - { - OverrideTableName = "OverrideTableName" - }; - - var context = new DynamoDBContext(client.Object, config); - - var query = context.Query("123", config); - var objects = query.ToList(); - - client.Verify(client => client.DescribeTable(It.Is(request => request.TableName == "OverrideTableName")), Times.Once()); - client.Verify(client => client.Query(It.Is(request => request.TableName == "OverrideTableName")), Times.Once()); - client.VerifyNoOtherCalls(); - } } }