diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs index d83c9e707fe9..416027f6c29e 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs @@ -331,7 +331,9 @@ private static bool ShouldSave(DynamoDBEntry entry, bool ignoreNullValues) throw new InvalidOperationException("Unrecognized DynamoDBEntry object"); } - // Deserializing DynamoDB document into an object + /// + /// Deserializes a DynamoDB document to an object + /// private T DocumentToObject(ItemStorage storage, DynamoDBFlatConfig flatConfig) { Type type = typeof(T); @@ -392,7 +394,9 @@ private void PopulateInstance(ItemStorage storage, object instance, DynamoDBFlat } } - // Serializing an object into a DynamoDB document + /// + /// Serializes an object into a DynamoDB document + /// private ItemStorage ObjectToItemStorage(T toStore, bool keysOnly, DynamoDBFlatConfig flatConfig) { if (toStore == null) return null; @@ -762,8 +766,10 @@ private static bool IsSupportedDictionaryType(Type type, out Type keyType, out T return true; } - // Deserializes a given Document to instance of targetType - // Use only for property conversions, not for full item conversion + /// + /// Deserializes a given Document to instance of targetType + /// Use only for property conversions, not for full item conversion + /// private object DeserializeFromDocument(Document document, Type targetType, DynamoDBFlatConfig flatConfig) { ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(targetType, flatConfig, conversionOnly: true); @@ -772,8 +778,11 @@ private object DeserializeFromDocument(Document document, Type targetType, Dynam object value = DocumentToObject(targetType, storage, flatConfig); return value; } - // Serializes a given value to Document - // Use only for property conversions, not for full item conversion + + /// + /// Serializes a given value to Document + /// Use only for property conversions, not for full item conversion + /// private Document SerializeToDocument(object value, Type type, DynamoDBFlatConfig flatConfig) { ItemStorageConfig config = StorageConfigCache.GetConfig(type, flatConfig, conversionOnly: true); @@ -782,7 +791,9 @@ private Document SerializeToDocument(object value, Type type, DynamoDBFlatConfig return doc; } - // Get/Set object properties + /// + /// Get/Set object properties + /// private static bool TrySetValue(object instance, MemberInfo member, object value) { FieldInfo fieldInfo = member as FieldInfo; @@ -825,7 +836,9 @@ private static bool TryGetValue(object instance, MemberInfo member, out object v } } - // Query/Scan building + /// + /// Query/Scan building + /// private ScanFilter ComposeScanFilter(IEnumerable conditions, ItemStorageConfig storageConfig, DynamoDBFlatConfig flatConfig) { ScanFilter filter = new ScanFilter(); diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/QueryConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/QueryConfig.cs new file mode 100644 index 000000000000..25fe58ce454f --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/QueryConfig.cs @@ -0,0 +1,104 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using Amazon.DynamoDBv2.DocumentModel; +using System; +using System.Collections.Generic; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the Query operation in the object-persistence programming model + /// +#if NET8_0_OR_GREATER + // The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] +#endif + public class QueryConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + /// Indicates the name of the index to query against. + /// This value is optional if the index name can be inferred from the call. + /// + public string IndexName { get; set; } + + /// + /// 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. 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 to . + /// + /// + /// Note: Conditions must be against non-key properties. + /// + public List QueryFilter { get; set; } + + /// + /// 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; } + + /// + /// 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; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.BackwardQuery = BackwardQuery; + config.IndexName = IndexName; + config.ConditionalOperator = ConditionalOperator; + config.QueryFilter = QueryFilter; + config.ConsistentRead = ConsistentRead; + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ScanConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ScanConfig.cs new file mode 100644 index 000000000000..53e2929eab58 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ScanConfig.cs @@ -0,0 +1,97 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using Amazon.DynamoDBv2.DocumentModel; +using System; +using System.Collections.Generic; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the Scan operation in the object-persistence programming model + /// +#if NET8_0_OR_GREATER + // The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] +#endif + public class ScanConfig : BaseOperationConfig + { + /// + /// Indicates the name of the index to scan against. + /// This value is optional if the index name can be inferred from the call. + /// + public string IndexName { get; set; } + + /// + /// 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; } + + /// + /// Filter for the Scan 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 to . + /// + /// + /// Note: Conditions must be against non-key properties. + /// + public List QueryFilter { get; set; } + + /// + /// 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; } + + /// + /// 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; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.IndexName = IndexName; + config.ConditionalOperator = ConditionalOperator; + config.QueryFilter = QueryFilter; + config.ConsistentRead = ConsistentRead; + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} 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 36f2b19ae108..0ae0a86a92dc 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -339,30 +339,39 @@ public Task ExecuteBatchGetAsync(params BatchGet[] batches) #region Scan async - /// - /// Configures an async Scan operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// - /// Conditions that the results should meet. - /// - /// Config object which can be used to override that table used. - /// AsyncSearch which can be used to retrieve DynamoDB data. + /// + public AsyncSearch ScanAsync(IEnumerable conditions) + { + var scan = ConvertScan(conditions, null); + return FromSearchAsync(scan); + } + + /// + [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) { var scan = ConvertScan(conditions, operationConfig); return FromSearchAsync(scan); } - /// - /// Configures an async Scan operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// Scan request object. - /// Config object which can be used to override the table used. - /// AsyncSearch which can be used to retrieve DynamoDB data. + /// + public AsyncSearch ScanAsync(IEnumerable conditions, ScanConfig scanConfig) + { + var scan = ConvertScan(conditions, scanConfig?.ToDynamoDBOperationConfig()); + return FromSearchAsync(scan); + } + + /// + public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig) + { + if (scanConfig == null) throw new ArgumentNullException("scanConfig"); + + var search = ConvertFromScan(scanConfig, null); + return FromSearchAsync(search); + } + + /// + [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) { if (scanConfig == null) throw new ArgumentNullException("scanConfig"); @@ -371,38 +380,53 @@ public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, DynamoDBO return FromSearchAsync(search); } + /// + public AsyncSearch FromScanAsync(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig) + { + if (scanConfig == null) throw new ArgumentNullException("scanConfig"); + + var search = ConvertFromScan(scanConfig, fromScanConfig?.ToDynamoDBOperationConfig()); + return FromSearchAsync(search); + } + #endregion #region Query async - /// - /// Configures an async Query operation against DynamoDB, finding items - /// that match the specified hash primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Config object which can be used to override the table used. - /// AsyncSearch which can be used to retrieve DynamoDB data. + /// + public AsyncSearch QueryAsync(object hashKeyValue) + { + var query = ConvertQueryByValue(hashKeyValue, null, null); + return FromSearchAsync(query); + } + + /// + [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) { var query = ConvertQueryByValue(hashKeyValue, null, operationConfig); return FromSearchAsync(query); } - /// - /// Configures an async Query operation against DynamoDB, finding items - /// that match the specified range element condition for a hash-and-range primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Operation of the condition. - /// - /// Value(s) of the condition. - /// For all operations except QueryOperator.Between, values should be one value. - /// For QueryOperator.Between, values should be two values. - /// - /// Config object which can be used to override the table used. - /// AsyncSearch which can be used to retrieve DynamoDB data. + /// + public AsyncSearch QueryAsync(object hashKeyValue, QueryConfig queryConfig) + { + var query = ConvertQueryByValue(hashKeyValue, null, queryConfig?.ToDynamoDBOperationConfig()); + return FromSearchAsync(query); + } + + /// + public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values) + { + if (values == null) + throw new ArgumentNullException("values"); + + var query = ConvertQueryByValue(hashKeyValue, op, values, null); + return FromSearchAsync(query); + } + + /// + [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) { if (values == null) @@ -412,14 +436,27 @@ public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnum return FromSearchAsync(query); } - /// - /// Configures an async Query operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// Query request object. - /// Config object which can be used to override the table used. - /// AsyncSearch which can be used to retrieve DynamoDB data. + /// + public AsyncSearch QueryAsync(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig) + { + if (values == null) + throw new ArgumentNullException("values"); + + var query = ConvertQueryByValue(hashKeyValue, op, values, queryConfig?.ToDynamoDBOperationConfig()); + return FromSearchAsync(query); + } + + /// + public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig) + { + if (queryConfig == null) throw new ArgumentNullException("queryConfig"); + + var search = ConvertFromQuery(queryConfig, null); + return FromSearchAsync(search); + } + + /// + [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) { if (queryConfig == null) throw new ArgumentNullException("queryConfig"); @@ -428,6 +465,15 @@ public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, Dynamo return FromSearchAsync(search); } + /// + public AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig) + { + if (queryConfig == null) throw new ArgumentNullException("queryConfig"); + + var search = ConvertFromQuery(queryConfig, fromQueryConfig?.ToDynamoDBOperationConfig()); + return FromSearchAsync(search); + } + #endregion } } 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 cc69466b2a99..7e963a79b8cb 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -19,7 +19,6 @@ using System.Threading; using System.Threading.Tasks; using Amazon.DynamoDBv2.DocumentModel; -using Amazon.DynamoDBv2.Model; namespace Amazon.DynamoDBv2.DataModel { @@ -259,7 +258,18 @@ partial interface IDynamoDBContext #region Scan async /// - /// Configures an async Scan operation against DynamoDB, finding items + /// Configures an async Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// + /// Conditions that the results should meet. + /// + /// AsyncSearch which can be used to retrieve DynamoDB data. + AsyncSearch ScanAsync(IEnumerable conditions); + + /// + /// Configures an async Scan operation against DynamoDB, finding items /// that match the specified conditions. /// /// Type of object. @@ -268,22 +278,65 @@ partial interface IDynamoDBContext /// /// Config object which can be used to override that table used. /// 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); /// - /// Configures an async Scan operation against DynamoDB, finding items + /// Configures an async Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// + /// Conditions that the results should meet. + /// + /// 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); + + /// + /// Configures an async Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// Scan request object. + /// AsyncSearch which can be used to retrieve DynamoDB data. + AsyncSearch FromScanAsync(ScanOperationConfig scanConfig); + + /// + /// Configures an async Scan operation against DynamoDB, finding items /// that match the specified conditions. /// /// Type of object. /// Scan request object. /// 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); + /// + /// Configures an async Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// 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); + #endregion #region Query async + /// + /// Configures an async Query operation against DynamoDB, finding items + /// that match the specified hash primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// AsyncSearch which can be used to retrieve DynamoDB data. + AsyncSearch QueryAsync(object hashKeyValue); + /// /// Configures an async Query operation against DynamoDB, finding items /// that match the specified hash primary key. @@ -292,8 +345,34 @@ partial interface IDynamoDBContext /// Hash key of the items to query. /// 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); + /// + /// Configures an async Query operation against DynamoDB, finding items + /// that match the specified hash primary key. + /// + /// Type of object. + /// 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); + + /// + /// Configures an async Query operation against DynamoDB, finding items + /// that match the specified range element condition for a hash-and-range primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// Operation of the condition. + /// + /// Value(s) of the condition. + /// For all operations except QueryOperator.Between, values should be one value. + /// 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); + /// /// Configures an async Query operation against DynamoDB, finding items /// that match the specified range element condition for a hash-and-range primary key. @@ -308,18 +387,55 @@ 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); + /// + /// Configures an async Query operation against DynamoDB, finding items + /// that match the specified range element condition for a hash-and-range primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// Operation of the condition. + /// + /// Value(s) of the condition. + /// For all operations except QueryOperator.Between, values should be one value. + /// For QueryOperator.Betwee, values should be two values. + /// + /// 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); + + /// + /// Configures an async Query operation against DynamoDB using a mid-level document model + /// query configration, finding items that match the specified conditions. + /// + /// Type of object. + /// Mid-level, document model query request object. + /// AsyncSearch which can be used to retrieve DynamoDB data. + AsyncSearch FromQueryAsync(QueryOperationConfig queryConfig); + /// /// Configures an async Query operation against DynamoDB, finding items /// that match the specified conditions. /// /// Type of object. - /// Query request object. + /// Mid-level, document model query request object. /// 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); + /// + /// Configures an async Query operation against DynamoDB using a mid-level document model + /// query configration, finding items that match the specified conditions. + /// + /// Type of object. + /// 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); + #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 c1067436bcbb..2109d13189c0 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -299,44 +299,38 @@ public void ExecuteTransactWrite(params TransactWrite[] transactionParts) #region Scan - /// - /// Executes a Scan operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// - /// Conditions that the results should meet. - /// - /// Lazy-loaded collection of results. + /// public IEnumerable Scan(params ScanCondition[] conditions) { - return Scan(conditions, null); + return Scan(conditions, (ScanConfig)null); } - /// - /// Executes a Scan operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// - /// Conditions that the results should meet. - /// - /// Config object which can be used to override that table used. - /// Lazy-loaded collection of results. + /// + [Obsolete("Use the Scan overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Scan.")] public IEnumerable Scan(IEnumerable conditions, DynamoDBOperationConfig operationConfig) { var scan = ConvertScan(conditions, operationConfig); return FromSearch(scan); } - /// - /// Executes a Scan operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// Scan request object. - /// Config object which can be used to override the table used. - /// Lazy-loaded collection of results. + /// + public IEnumerable Scan(IEnumerable conditions, ScanConfig scanConfig) + { + var scan = ConvertScan(conditions, scanConfig?.ToDynamoDBOperationConfig()); + return FromSearch(scan); + } + + /// + public IEnumerable FromScan(ScanOperationConfig scanConfig) + { + if (scanConfig == null) throw new ArgumentNullException("scanConfig"); + + var search = ConvertFromScan(scanConfig, null); + return FromSearch(search); + } + + /// + [Obsolete("Use the FromScan overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromScan.")] public IEnumerable FromScan(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null) { if (scanConfig == null) throw new ArgumentNullException("scanConfig"); @@ -345,72 +339,52 @@ public IEnumerable FromScan(ScanOperationConfig scanConfig, DynamoDBOperat return FromSearch(search); } + /// + public IEnumerable FromScan(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig) + { + if (scanConfig == null) throw new ArgumentNullException("scanConfig"); + + var search = ConvertFromScan(scanConfig, fromScanConfig?.ToDynamoDBOperationConfig()); + return FromSearch(search); + } + #endregion #region Query - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified hash primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Lazy-loaded collection of results. + /// public IEnumerable Query(object hashKeyValue) { var query = ConvertQueryByValue(hashKeyValue, null, null); return FromSearch(query); } - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified hash primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Config object which can be used to override the table used. - /// Lazy-loaded collection of results. + /// + [Obsolete("Use the Query overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Query.")] public IEnumerable Query(object hashKeyValue, DynamoDBOperationConfig operationConfig) { var query = ConvertQueryByValue(hashKeyValue, null, operationConfig); return FromSearch(query); } - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified range element condition for a hash-and-range primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Operation of the condition. - /// - /// Value(s) of the condition. - /// For all operations except QueryOperator.Between, values should be one value. - /// For QueryOperator.Betwee, values should be two values. - /// - /// Lazy-loaded collection of results. + /// + public IEnumerable Query(object hashKeyValue, QueryConfig queryConfig) + { + var query = ConvertQueryByValue(hashKeyValue, null, queryConfig?.ToDynamoDBOperationConfig()); + return FromSearch(query); + } + + /// public IEnumerable Query(object hashKeyValue, QueryOperator op, params object[] values) { if (values == null || values.Length == 0) throw new ArgumentOutOfRangeException("values"); - return Query(hashKeyValue, op, values, null); + return Query(hashKeyValue, op, values, (QueryConfig)null); } - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified range element condition for a hash-and-range primary key. - /// - /// Type of object. - /// Hash key of the items to query. - /// Operation of the condition. - /// - /// Value(s) of the condition. - /// For all operations except QueryOperator.Between, values should be one value. - /// For QueryOperator.Betwee, values should be two values. - /// - /// Config object which can be used to override the table used. - /// Lazy-loaded collection of results. + /// + [Obsolete("Use the Query overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Query.")] public IEnumerable Query(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig) { if (values == null) @@ -420,26 +394,24 @@ public IEnumerable Query(object hashKeyValue, QueryOperator op, IEnumerabl return FromSearch(query); } - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// Query request object. - /// Lazy-loaded collection of results. + /// + public IEnumerable Query(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig) + { + if (values == null) + throw new ArgumentNullException("values"); + + var query = ConvertQueryByValue(hashKeyValue, op, values, queryConfig?.ToDynamoDBOperationConfig()); + return FromSearch(query); + } + + /// public IEnumerable FromQuery(QueryOperationConfig queryConfig) { - return FromQuery(queryConfig, null); + return FromQuery(queryConfig, (FromQueryConfig)null); } - /// - /// Executes a Query operation against DynamoDB, finding items - /// that match the specified conditions. - /// - /// Type of object. - /// Query request object. - /// Config object which can be used to override the table used. - /// Lazy-loaded collection of results. + /// + [Obsolete("Use the FromQuery overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromQuery.")] public IEnumerable FromQuery(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig) { if (queryConfig == null) throw new ArgumentNullException("queryConfig"); @@ -448,6 +420,15 @@ public IEnumerable FromQuery(QueryOperationConfig queryConfig, DynamoDBOpe return FromSearch(search); } + /// + public IEnumerable FromQuery(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig) + { + if (queryConfig == null) throw new ArgumentNullException("queryConfig"); + + var search = ConvertFromQuery(queryConfig, fromQueryConfig?.ToDynamoDBOperationConfig()); + return FromSearch(search); + } + #endregion #region Table methods 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 b443b199f61a..8f242995b5b1 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -272,8 +272,32 @@ partial interface IDynamoDBContext /// /// Config object which can be used to override that table used. /// Lazy-loaded collection of results. + /// + [Obsolete("Use the Scan overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Scan.")] IEnumerable Scan(IEnumerable conditions, DynamoDBOperationConfig operationConfig); + /// + /// Executes a Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// + /// Conditions that the results should meet. + /// + /// Config object that can be used to override properties on the table's context for this request. + /// Lazy-loaded collection of results. + IEnumerable Scan(IEnumerable conditions, ScanConfig scanConfig); + + /// + /// Executes a Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// Scan request object. + /// Lazy-loaded collection of results. + + IEnumerable FromScan(ScanOperationConfig scanConfig); + /// /// Executes a Scan operation against DynamoDB, finding items /// that match the specified conditions. @@ -282,12 +306,32 @@ partial interface IDynamoDBContext /// Scan request object. /// Config object which can be used to override the table used. /// Lazy-loaded collection of results. + [Obsolete("Use the FromScan overload that takes ScanConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromScan.")] IEnumerable FromScan(ScanOperationConfig scanConfig, DynamoDBOperationConfig operationConfig = null); + /// + /// Executes a Scan operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// Scan request object. + /// Config object that can be used to override properties on the table's context for this request. + /// Lazy-loaded collection of results. + IEnumerable FromScan(ScanOperationConfig scanConfig, FromScanConfig fromScanConfig); + #endregion #region Query + /// + /// Executes a Query operation against DynamoDB, finding items + /// that match the specified hash primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// Lazy-loaded collection of results. + IEnumerable Query(object hashKeyValue); + /// /// Executes a Query operation against DynamoDB, finding items /// that match the specified hash primary key. @@ -296,8 +340,19 @@ partial interface IDynamoDBContext /// Hash key of the items to query. /// Config object which can be used to override the table used. /// Lazy-loaded collection of results. + [Obsolete("Use the Query overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Query.")] IEnumerable Query(object hashKeyValue, DynamoDBOperationConfig operationConfig = null); + /// + /// Executes a Query operation against DynamoDB, finding items + /// that match the specified hash primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// Config object that can be used to override properties on the table's context for this request. + /// Lazy-loaded collection of results. + IEnumerable Query(object hashKeyValue, QueryConfig queryConfig); + /// /// Executes a Query operation against DynamoDB, finding items /// that match the specified range element condition for a hash-and-range primary key. @@ -327,8 +382,34 @@ partial interface IDynamoDBContext /// /// Config object which can be used to override the table used. /// Lazy-loaded collection of results. + [Obsolete("Use the Query overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Query.")] + IEnumerable Query(object hashKeyValue, QueryOperator op, IEnumerable values, DynamoDBOperationConfig operationConfig); + /// + /// Executes a Query operation against DynamoDB, finding items + /// that match the specified range element condition for a hash-and-range primary key. + /// + /// Type of object. + /// Hash key of the items to query. + /// Operation of the condition. + /// + /// Value(s) of the condition. + /// For all operations except QueryOperator.Between, values should be one value. + /// For QueryOperator.Betwee, values should be two values. + /// + /// Config object that can be used to override properties on the table's context for this request. + /// Lazy-loaded collection of results. + IEnumerable Query(object hashKeyValue, QueryOperator op, IEnumerable values, QueryConfig queryConfig); + + /// + /// Executes a Query operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// Query request object. + /// Lazy-loaded collection of results. + IEnumerable FromQuery(QueryOperationConfig queryConfig); /// /// Executes a Query operation against DynamoDB, finding items @@ -338,8 +419,20 @@ partial interface IDynamoDBContext /// Query request object. /// Config object which can be used to override the table used. /// Lazy-loaded collection of results. + [Obsolete("Use the FromQuery overload that takes QueryConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromQuery.")] + IEnumerable FromQuery(QueryOperationConfig queryConfig, DynamoDBOperationConfig operationConfig = null); + /// + /// Executes a Query operation against DynamoDB, finding items + /// that match the specified conditions. + /// + /// Type of object. + /// Query request object. + /// Config object that can be used to override properties on the table's context for this request. + /// Lazy-loaded collection of results. + IEnumerable FromQuery(QueryOperationConfig queryConfig, FromQueryConfig fromQueryConfig); + #endregion #region Table methods diff --git a/sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs new file mode 100644 index 000000000000..8b1c1d418648 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs @@ -0,0 +1,49 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using System; +using Amazon.DynamoDBv2.DocumentModel; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Additional input for the FromQuery operation in the object-persistence programming model. This supplements + /// , which is shared between the document and object-persistence models. + /// +#if NET8_0_OR_GREATER + // The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] +#endif + public class FromQueryConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs new file mode 100644 index 000000000000..fde94a66ccbd --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using Amazon.DynamoDBv2.DocumentModel; +using System; +using System.Collections.Generic; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Additional input for the FromScan operation in the object-persistence programming model. This supplements + /// , which is shared between the document and object-persistence models. + /// +#if NET8_0_OR_GREATER + // The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)] +#endif + public class FromScanConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs index e2ddd10b4a1f..ff553e85ff1a 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs @@ -345,7 +345,9 @@ public void TestContext_RetrieveDateTimeInUtc_OperationConfig(bool retrieveDateT // Query QueryFilter filter = new QueryFilter(); filter.AddCondition("CreationTime", QueryOperator.Equal, currTime); - storedEmployee = Context.FromQuery(new QueryOperationConfig { Filter = filter }, operationConfig).First(); + storedEmployee = Context.FromQuery( + new QueryOperationConfig { Filter = filter }, + new FromQueryConfig { RetrieveDateTimeInUtc = retrieveDateTimeInUtc}).First(); Assert.IsNotNull(storedEmployee); ApproximatelyEqual(expectedCurrTime, storedEmployee.CreationTime); ApproximatelyEqual(expectedCurrTime, storedEmployee.EpochDate2); @@ -355,7 +357,9 @@ public void TestContext_RetrieveDateTimeInUtc_OperationConfig(bool retrieveDateT Assert.AreEqual(employee.Age, storedEmployee.Age); // Scan - storedEmployee = Context.Scan(new List(), operationConfig).First(); + storedEmployee = Context.Scan( + new List(), + new ScanConfig { RetrieveDateTimeInUtc = retrieveDateTimeInUtc }).First(); Assert.IsNotNull(storedEmployee); ApproximatelyEqual(expectedCurrTime, storedEmployee.CreationTime); ApproximatelyEqual(expectedCurrTime, storedEmployee.EpochDate2); @@ -942,7 +946,7 @@ private void TestHashObjects() product.CompanyName, // Hash-key for the index is Company QueryOperator.GreaterThan, // Range-key for the index is Price, so the new object[] { 90 }, // condition is against a numerical value - new DynamoDBOperationConfig // Configure the index to use + new QueryConfig // Configure the index to use { IndexName = "GlobalIndex", }); @@ -953,7 +957,7 @@ private void TestHashObjects() product.CompanyName, // Hash-key for the index is Company QueryOperator.GreaterThan, // Range-key for the index is Price, so the new object[] { 90 }, // condition is against a numerical value - new DynamoDBOperationConfig // Configure the index to use + new QueryConfig // Configure the index to use { IndexName = "GlobalIndex", QueryFilter = new List @@ -975,7 +979,7 @@ private void TestHashObjects() // Scan the table with consistent read products = Context.Scan( new ScanCondition[] { }, - new DynamoDBOperationConfig { ConsistentRead = true }); + new ScanConfig { ConsistentRead = true }); Assert.AreEqual(1, products.Count()); // Test a versioned product @@ -1089,21 +1093,21 @@ private void TestHashObjects() // Index Query // Query local index for items with Hash-Key = "Diane" - employees = Context.Query("Diane", new DynamoDBOperationConfig { IndexName = "LocalIndex" }).ToList(); + employees = Context.Query("Diane", new QueryConfig { IndexName = "LocalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Query local index for items with Hash-Key = "Diane" and Range-Key = "Eva" employees = Context.Query("Diane", QueryOperator.Equal, new object[] { "Eva" }, - new DynamoDBOperationConfig { IndexName = "LocalIndex" }).ToList(); + new QueryConfig { IndexName = "LocalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Query global index for item with Hash-Key (Company) = "Big River" - employees = Context.Query("Big River", new DynamoDBOperationConfig { IndexName = "GlobalIndex" }).ToList(); + employees = Context.Query("Big River", new QueryConfig { IndexName = "GlobalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Query global index for item with Hash-Key (Company) = "Big River", with QueryFilter for CurrentStatus = Status.Active employees = Context.Query("Big River", - new DynamoDBOperationConfig + new QueryConfig { IndexName = "GlobalIndex", QueryFilter = new List @@ -1119,7 +1123,7 @@ private void TestHashObjects() // Scan local index for items with Hash-Key = "Diane" employees = Context.Scan( new List { new ScanCondition("Name", ScanOperator.Equal, "Diane") }, - new DynamoDBOperationConfig { IndexName = "LocalIndex" }).ToList(); + new ScanConfig { IndexName = "LocalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Scan local index for items with Hash-Key = "Diane" and Range-Key = "Eva" @@ -1129,13 +1133,13 @@ private void TestHashObjects() new ScanCondition("Name", ScanOperator.Equal, "Diane"), new ScanCondition("ManagerName", ScanOperator.Equal, "Eva") }, - new DynamoDBOperationConfig { IndexName = "LocalIndex" }).ToList(); + new ScanConfig { IndexName = "LocalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Scan global index for item with Hash-Key (Company) = "Big River" employees = Context.Scan( new List { new ScanCondition("CompanyName", ScanOperator.Equal, "Big River") }, - new DynamoDBOperationConfig { IndexName = "GlobalIndex" }).ToList(); + new ScanConfig { IndexName = "GlobalIndex" }).ToList(); Assert.AreEqual(2, employees.Count); // Scan global index for item with Hash-Key (Company) = "Big River", with QueryFilter for CurrentStatus = Status.Active @@ -1145,7 +1149,7 @@ private void TestHashObjects() new ScanCondition("CompanyName", ScanOperator.Equal, "Big River"), new ScanCondition("CurrentStatus", ScanOperator.Equal, Status.Active) }, - new DynamoDBOperationConfig + new ScanConfig { IndexName = "GlobalIndex" }).ToList(); diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs index 7c00ee205772..49a66b677a20 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs @@ -1,13 +1,16 @@ using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; +using Amazon.DynamoDBv2.DocumentModel; using Amazon.DynamoDBv2.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using System.Linq; namespace AWSSDK_DotNet.UnitTests { /// - /// These tests that new DynamoDB operation-specific properties are plumbed + /// These tests serve as a reminder to developers and reviewers to + /// ensure that new DynamoDB operation-specific properties are plumbed /// into the internal code paths correctly /// [TestClass] @@ -38,7 +41,8 @@ public void BatchGetConfig_OverridesTableName() .Verifiable(); // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used - var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig { + var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig + { TableNamePrefix = "ContextPrefix-", DisableFetchingTableMetadata = true }); @@ -46,7 +50,7 @@ public void BatchGetConfig_OverridesTableName() var batchGetConfig = new BatchGetConfig() { TableNamePrefix = "OperationPrefix-" }; var batchGet = context.CreateBatchGet(batchGetConfig); - batchGet.AddKey("123"); + batchGet.AddKey("123", "Name"); batchGet.Execute(); // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown @@ -66,7 +70,7 @@ public void BatchWriteConfig_OverridesTableName() { var mockClient = new Mock(); mockClient.Setup(x => x.BatchWriteItem(It.Is(x => x.RequestItems.ContainsKey("OperationPrefix-TableName")))) - .Returns(new BatchWriteItemResponse { UnprocessedItems = new() }) + .Returns(new BatchWriteItemResponse { UnprocessedItems = new() }) .Verifiable(); // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used @@ -79,7 +83,7 @@ public void BatchWriteConfig_OverridesTableName() var batchWriteConfig = new BatchWriteConfig() { TableNamePrefix = "OperationPrefix-" }; var batchWrite = context.CreateBatchWrite(batchWriteConfig); - batchWrite.AddPutItem(new DataModel { Id = "123" }); + batchWrite.AddPutItem(new DataModel { Id = "123", Name = "Name" }); batchWrite.Execute(); // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown @@ -112,7 +116,7 @@ public void TransactGetConfig_OverridesTableName() var transactGetConfig = new TransactGetConfig() { TableNamePrefix = "OperationPrefix-" }; var transactGet = context.CreateTransactGet(transactGetConfig); - transactGet.AddKey("123"); + transactGet.AddKey("123", "Name"); transactGet.Execute(); // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown @@ -152,11 +156,147 @@ public void TransactWriteConfig_OverridesTableName() mockClient.VerifyAll(); } + [TestMethod] + 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); + } + + [TestMethod] + public void QueryConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.Query(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new QueryResponse { Items = new() }) + .Verifiable(); + + // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used + var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig + { + TableNamePrefix = "ContextPrefix-", + DisableFetchingTableMetadata = true + }); + + var queryConfig = new QueryConfig() { TableNamePrefix = "OperationPrefix-" }; + + var query = context.Query("123", queryConfig); + query.ToList(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void FromQueryConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.Query(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new QueryResponse { Items = new() }) + .Verifiable(); + + // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used + var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig + { + TableNamePrefix = "ContextPrefix-", + DisableFetchingTableMetadata = true + }); + + var queryOperationConfig = new QueryOperationConfig() + { + Filter = new QueryFilter("Id", QueryOperator.Equal, "123") + }; + + var fromQueryConfig = new FromQueryConfig() { TableNamePrefix = "OperationPrefix-" }; + + var query = context.FromQuery(queryOperationConfig, fromQueryConfig); + query.ToList(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void ScanConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.Scan(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new ScanResponse { Items = new() }) + .Verifiable(); + + // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used + var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig + { + TableNamePrefix = "ContextPrefix-", + DisableFetchingTableMetadata = true + }); + + var scanConfig = new ScanConfig() { TableNamePrefix = "OperationPrefix-" }; + + var scan = context.Scan(new ScanCondition[0], scanConfig); + scan.ToList(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void FromScanConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.Scan(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new ScanResponse { Items = new() }) + .Verifiable(); + + // Set a prefix on the context config, but we'll override it on the operation config so we don't expect it to be used + var context = new DynamoDBContext(mockClient.Object, new DynamoDBContextConfig + { + TableNamePrefix = "ContextPrefix-", + DisableFetchingTableMetadata = true + }); + + var fromScanConfig = new FromScanConfig() { TableNamePrefix = "OperationPrefix-" }; + + var scan = context.FromScan(new ScanOperationConfig(), fromScanConfig); + scan.ToList(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + [DynamoDBTable("TableName")] private class DataModel { [DynamoDBHashKey] public string Id { get; set; } + + [DynamoDBRangeKey] + public string Name { get; set; } } } } diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs index 228c1f05bd1f..cfe1d469cac8 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs @@ -435,8 +435,7 @@ public async Task TestMockingAsyncSeach() var mockDBContext = new Mock(); mockDBContext .Setup(x => x.ScanAsync( - It.IsAny>(), - It.IsAny())) + It.IsAny>())) .Returns( new MockAsyncSearch() // Return mock version of AsyncSearch );