From 57a5269dc6dd3e035b1484ebd08b5fbd650fb55c Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Wed, 10 Jul 2024 15:42:27 -0400 Subject: [PATCH 1/8] Add base class for upcoming object persistence operation-specific config objects (#3380) --- .../Custom/DataModel/BaseOperationConfig.cs | 101 ++++++++++++++++++ .../DataModelOperationSpecificConfigTests.cs | 22 ++++ 2 files changed, 123 insertions(+) create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs new file mode 100644 index 000000000000..5f52b622ba09 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs @@ -0,0 +1,101 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Base class for operation-specific configurations for DynamoDB object persistence operations. + /// + /// + /// This should only contain members that are relevant to all object persistence operations, + /// anything operation-specific should be added to derived classes. + /// +#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 abstract class BaseOperationConfig + { + /// + /// Indicates which DynamoDB table to use. This overrides the table specified + /// by the on the .NET objects that you're saving or loading. + /// + public string OverrideTableName { get; set; } + + /// + /// Directs to prefix all table names + /// with a specific string. If this 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 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. + /// + public DynamoDBEntryConversion Conversion { get; set; } + + /// + /// Contorls how interprets emptry string values. + /// If the property is false (or not set), empty string values will be + /// interpreted as null values. + /// + public bool? IsEmptyStringValueEnabled { get; set; } + + /// + /// Converts this to the shared + /// + /// + /// Users should interact with the new, operation-specific configs, but we + /// convert to the internal shared config for the internal code paths. + /// + /// A new with settings copied from the operation-specific config + internal virtual DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + return new DynamoDBOperationConfig() + { + OverrideTableName = OverrideTableName, + TableNamePrefix = TableNamePrefix, + MetadataCachingMode = MetadataCachingMode, + DisableFetchingTableMetadata = DisableFetchingTableMetadata, + Conversion = Conversion, + IsEmptyStringValueEnabled = IsEmptyStringValueEnabled + }; + } + } +} diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs new file mode 100644 index 000000000000..0ecf3bc18180 --- /dev/null +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs @@ -0,0 +1,22 @@ +using Amazon.DynamoDBv2.DataModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace AWSSDK_DotNet.UnitTests +{ + /// + /// 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] + public class DataModelOperationSpecificConfigTests + { + [TestMethod] + 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); + } + } +} From c20cafe84fc63401c8651236cd6ea47d5120fbab Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Tue, 30 Jul 2024 14:53:41 -0400 Subject: [PATCH 2/8] Create separate operation-specific configs for the object-persistence Batch and Transact operations (#3376) --- .../Custom/DataModel/BaseOperationConfig.cs | 2 +- .../Custom/DataModel/BatchGetConfig.cs | 58 +++++++ .../Custom/DataModel/BatchWriteConfig.cs | 52 +++++++ .../DynamoDBv2/Custom/DataModel/Context.cs | 99 +++++++++++- .../Custom/DataModel/IDynamoDBContext.cs | 104 +++++++++++++ .../Custom/DataModel/TransactGetConfig.cs | 47 ++++++ .../Custom/DataModel/TransactWriteConfig.cs | 44 ++++++ .../DataModelOperationSpecificConfigTests.cs | 146 +++++++++++++++++- 8 files changed, 541 insertions(+), 11 deletions(-) create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGetConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWriteConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGetConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWriteConfig.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs index 5f52b622ba09..e8a5a5ea8759 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BaseOperationConfig.cs @@ -71,7 +71,7 @@ public abstract class BaseOperationConfig public DynamoDBEntryConversion Conversion { get; set; } /// - /// Contorls how interprets emptry string values. + /// Controls how interprets empty string values. /// If the property is false (or not set), empty string values will be /// interpreted as null values. /// diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGetConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGetConfig.cs new file mode 100644 index 000000000000..f7fb57066ee2 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchGetConfig.cs @@ -0,0 +1,58 @@ +/* + * 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; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the BatchGet 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 BatchGetConfig : BaseOperationConfig + { + /// + /// 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.ConsistentRead = ConsistentRead; + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWriteConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWriteConfig.cs new file mode 100644 index 000000000000..d96bb4bb93e9 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWriteConfig.cs @@ -0,0 +1,52 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the BatchWrite 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 BatchWriteConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + /// Directs to ignore null values when + /// converting an object to a DynamoDB item. If the property is false + /// (or not set), null values will be interpreted as directives to + /// delete the specific attributes on the DynamoDB item. + /// + public bool? IgnoreNullValues { get; set; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.SkipVersionCheck = SkipVersionCheck; + config.IgnoreNullValues = IgnoreNullValues; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 80e4b78ed8e9..80e9d1458b42 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -19,7 +19,6 @@ #if AWS_ASYNC_API using System.Threading.Tasks; #endif -using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DocumentModel; namespace Amazon.DynamoDBv2.DataModel @@ -208,7 +207,7 @@ public void Dispose() #endregion - #region Factory Creates + #region BatchGet /// /// Creates a strongly-typed BatchGet object, allowing @@ -218,7 +217,7 @@ public void Dispose() /// Empty strongly-typed BatchGet object public BatchGet CreateBatchGet() { - return CreateBatchGet(null); + return CreateBatchGet((BatchGetConfig)null); } /// @@ -228,12 +227,25 @@ public BatchGet CreateBatchGet() /// 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) { 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) + { + return new BatchGet(this, new DynamoDBFlatConfig(batchGetConfig?.ToDynamoDBOperationConfig(), Config)); + } + /// /// Creates a MultiTableBatchGet object, composed of multiple /// individual BatchGet objects. @@ -245,6 +257,10 @@ public MultiTableBatchGet CreateMultiTableBatchGet(params BatchGet[] batches) return new MultiTableBatchGet(batches); } + #endregion + + #region BatchWrite + /// /// Creates a strongly-typed BatchWrite object, allowing /// a batch-write operation against DynamoDB. @@ -253,7 +269,7 @@ public MultiTableBatchGet CreateMultiTableBatchGet(params BatchGet[] batches) /// Empty strongly-typed BatchWrite object public BatchWrite CreateBatchWrite() { - return CreateBatchWrite(null); + return CreateBatchWrite((BatchWriteConfig)null); } /// @@ -263,6 +279,7 @@ public BatchWrite CreateBatchWrite() /// 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) { DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); @@ -283,7 +300,7 @@ public BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig /// Empty strongly-typed BatchWrite object public BatchWrite CreateBatchWrite(Type valuesType) { - return CreateBatchWrite(valuesType, null); + return CreateBatchWrite(valuesType, (BatchWriteConfig)null); } /// @@ -299,12 +316,43 @@ public BatchWrite CreateBatchWrite(Type valuesType) /// 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) { 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) + { + 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) + { + return new BatchWrite(this, valuesType, new DynamoDBFlatConfig(batchWriteConfig.ToDynamoDBOperationConfig(), Config)); + } + /// /// Creates a MultiTableBatchWrite object, composed of multiple /// individual BatchWrite objects. @@ -316,6 +364,10 @@ public MultiTableBatchWrite CreateMultiTableBatchWrite(params BatchWrite[] batch return new MultiTableBatchWrite(batches); } + #endregion + + #region TransactGet + /// /// Creates a strongly-typed TransactGet object, allowing /// a transactional get operation against DynamoDB. @@ -324,7 +376,7 @@ public MultiTableBatchWrite CreateMultiTableBatchWrite(params BatchWrite[] batch /// Empty strongly-typed TransactGet object. public TransactGet CreateTransactGet() { - return CreateTransactGet(null); + return CreateTransactGet((TransactGetConfig)null); } /// @@ -334,12 +386,26 @@ public TransactGet CreateTransactGet() /// 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) { 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) + { + DynamoDBFlatConfig config = new DynamoDBFlatConfig(transactGetConfig?.ToDynamoDBOperationConfig(), this.Config); + return new TransactGet(this, config); + } + /// /// Creates a MultiTableTransactGet object, composed of multiple /// individual TransactGet objects. @@ -351,6 +417,10 @@ public MultiTableTransactGet CreateMultiTableTransactGet(params TransactGet[] tr return new MultiTableTransactGet(transactionParts); } + #endregion + + #region TransactWrite + /// /// Creates a strongly-typed TransactWrite object, allowing /// a transactional write operation against DynamoDB. @@ -359,7 +429,7 @@ public MultiTableTransactGet CreateMultiTableTransactGet(params TransactGet[] tr /// Empty strongly-typed TransactWrite object. public TransactWrite CreateTransactWrite() { - return CreateTransactWrite(null); + return CreateTransactWrite((TransactWriteConfig)null); } /// @@ -369,12 +439,27 @@ public TransactWrite CreateTransactWrite() /// 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) { 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) + { + DynamoDBFlatConfig config = new DynamoDBFlatConfig(transactWriteConfig?.ToDynamoDBOperationConfig(), this.Config); + return new TransactWrite(this, config); + } + /// /// Creates a MultiTableTransactWrite object, composed of multiple /// individual TransactWrite objects. diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index 4270efccaa08..17868bbf21f2 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -113,6 +113,15 @@ public partial interface IDynamoDBContext : IDisposable #endregion #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 + BatchGet CreateBatchGet(); + /// /// Creates a strongly-typed BatchGet object, allowing /// a batch-get operation against DynamoDB. @@ -120,8 +129,18 @@ 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 + [Obsolete("Use the CreateBatchGet overload that takes BatchGetConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchGet.")] BatchGet CreateBatchGet(DynamoDBOperationConfig operationConfig = null); + /// + /// 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); + /// /// Creates a MultiTableBatchGet object, composed of multiple /// individual BatchGet objects. @@ -134,6 +153,14 @@ public partial interface IDynamoDBContext : IDisposable #region Batch Write + /// + /// Creates a strongly-typed BatchWrite object, allowing + /// a batch-write operation against DynamoDB. + /// + /// Type of objects to write + /// Empty strongly-typed BatchWrite object + BatchWrite CreateBatchWrite(); + /// /// Creates a strongly-typed BatchWrite object, allowing /// a batch-write operation against DynamoDB. @@ -141,8 +168,24 @@ public partial interface IDynamoDBContext : IDisposable /// 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.")] + BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig = 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. + /// + /// The type of data which will be persisted in this batch. + /// Empty strongly-typed BatchWrite object + BatchWrite CreateBatchWrite(Type valuesType); + /// /// Creates a strongly-typed BatchWrite object, allowing /// a batch-write operation against DynamoDB. @@ -156,8 +199,33 @@ public partial interface IDynamoDBContext : IDisposable /// The type of data which will be persisted in this batch. /// 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); + /// + /// 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 + BatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig); + + /// + /// 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 + BatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig); + /// /// Creates a MultiTableBatchWrite object, composed of multiple /// individual BatchWrite objects. @@ -170,6 +238,14 @@ public partial interface IDynamoDBContext : IDisposable #region Transact Get + /// + /// Creates a strongly-typed TransactGet object, allowing + /// a transactional get operation against DynamoDB. + /// + /// Type of objects to get. + /// Empty strongly-typed TransactGet object. + TransactGet CreateTransactGet(); + /// /// Creates a strongly-typed TransactGet object, allowing /// a transactional get operation against DynamoDB. @@ -177,8 +253,18 @@ public partial interface IDynamoDBContext : IDisposable /// 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.")] TransactGet CreateTransactGet(DynamoDBOperationConfig operationConfig = null); + /// + /// 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. + TransactGet CreateTransactGet(TransactGetConfig transactGetConfig); + /// /// Creates a MultiTableTransactGet object, composed of multiple /// individual TransactGet objects. @@ -191,6 +277,14 @@ public partial interface IDynamoDBContext : IDisposable #region Transact Write + /// + /// Creates a strongly-typed TransactWrite object, allowing + /// a transactional write operation against DynamoDB. + /// + /// Type of objects to write. + /// Empty strongly-typed TransactWrite object. + TransactWrite CreateTransactWrite(); + /// /// Creates a strongly-typed TransactWrite object, allowing /// a transactional write operation against DynamoDB. @@ -198,8 +292,18 @@ public partial interface IDynamoDBContext : IDisposable /// 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.")] TransactWrite CreateTransactWrite(DynamoDBOperationConfig operationConfig = null); + /// + /// 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. + TransactWrite CreateTransactWrite(TransactWriteConfig transactWriteConfig); + /// /// Creates a MultiTableTransactWrite object, composed of multiple /// individual TransactWrite objects. diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGetConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGetConfig.cs new file mode 100644 index 000000000000..2b4749a46081 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactGetConfig.cs @@ -0,0 +1,47 @@ +/* + * 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; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the TransactGet 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 TransactGetConfig : 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/DataModel/TransactWriteConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWriteConfig.cs new file mode 100644 index 000000000000..7e7231d12ae0 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/TransactWriteConfig.cs @@ -0,0 +1,44 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the TransactWrite 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 TransactWriteConfig : BaseOperationConfig + { + /// + /// Directs to ignore null values when + /// converting an object to a DynamoDB item. If the property is false + /// (or not set), null values will be interpreted as directives to + /// delete the specific attributes on the DynamoDB item. + /// + public bool? IgnoreNullValues { get; set; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.IgnoreNullValues = IgnoreNullValues; + + return config; + } + } +} diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs index 0ecf3bc18180..7c00ee205772 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs @@ -1,11 +1,13 @@ -using Amazon.DynamoDBv2.DataModel; +using Amazon.DynamoDBv2; +using Amazon.DynamoDBv2.DataModel; +using Amazon.DynamoDBv2.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace AWSSDK_DotNet.UnitTests { /// - /// These tests serve as a reminder to developers and reviewers to - /// ensure that new DynamoDB operation-specific properties are plumbed + /// These tests that new DynamoDB operation-specific properties are plumbed /// into the internal code paths correctly /// [TestClass] @@ -18,5 +20,143 @@ public void BaseOperationConfig() // `ToDynamoDBOperationConfig` before updating this unit test Assert.AreEqual(6, typeof(BaseOperationConfig).GetProperties().Length); } + + [TestMethod] + 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); + } + + [TestMethod] + public void BatchGetConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.BatchGetItem(It.Is(request => request.RequestItems.ContainsKey("OperationPrefix-TableName")))) + .Returns(new BatchGetItemResponse { Responses = new(), UnprocessedKeys = 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 batchGetConfig = new BatchGetConfig() { TableNamePrefix = "OperationPrefix-" }; + + var batchGet = context.CreateBatchGet(batchGetConfig); + batchGet.AddKey("123"); + batchGet.Execute(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + 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() }) + .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 batchWriteConfig = new BatchWriteConfig() { TableNamePrefix = "OperationPrefix-" }; + + var batchWrite = context.CreateBatchWrite(batchWriteConfig); + batchWrite.AddPutItem(new DataModel { Id = "123" }); + batchWrite.Execute(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void TransactGetConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(x => x.TransactGetItems(It.Is(x => x.TransactItems[0].Get.TableName == "OperationPrefix-TableName"))) + .Returns(new TransactGetItemsResponse { Responses = 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 transactGetConfig = new TransactGetConfig() { TableNamePrefix = "OperationPrefix-" }; + + var transactGet = context.CreateTransactGet(transactGetConfig); + transactGet.AddKey("123"); + transactGet.Execute(); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void TransactWriteConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(x => x.TransactWriteItems(It.Is(x => x.TransactItems[0].Update.TableName == "OperationPrefix-TableName"))) + .Returns(new TransactWriteItemsResponse()) + .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 transactWriteConfig = new TransactWriteConfig { TableNamePrefix = "OperationPrefix-" }; + + var transactWrite = context.CreateTransactWrite(transactWriteConfig); + transactWrite.AddSaveItem(new DataModel { Id = "123" }); + transactWrite.Execute(); + + // 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; } + } } } From bc091a6765e69fba4b894827c50bbe2e0dd715bf Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Tue, 30 Jul 2024 15:26:04 -0400 Subject: [PATCH 3/8] Create separate operation-specific configs for the object-persistence Scan and Query operations (#3383) --- .../Custom/DataModel/ContextInternal.cs | 29 +++- .../Custom/DataModel/QueryConfig.cs | 104 ++++++++++++ .../DynamoDBv2/Custom/DataModel/ScanConfig.cs | 97 +++++++++++ .../Custom/DataModel/_async/Context.Async.cs | 142 ++++++++++------ .../_async/IDynamoDBContext.Async.cs | 124 +++++++++++++- .../Custom/DataModel/_bcl/Context.Sync.cs | 155 ++++++++---------- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 93 +++++++++++ .../DynamoDBv2/Custom/FromQueryConfig.cs | 49 ++++++ .../DynamoDBv2/Custom/FromScanConfig.cs | 50 ++++++ .../IntegrationTests/DataModelTests.cs | 31 ++-- .../DataModelOperationSpecificConfigTests.cs | 152 ++++++++++++++++- 11 files changed, 860 insertions(+), 166 deletions(-) create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/QueryConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/ScanConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs index c6d94e93d6e7..3b8199cc050d 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; @@ -769,8 +773,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); @@ -779,8 +785,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); @@ -789,7 +798,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; @@ -832,7 +843,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 959c44d93d50..f65ff104d0fc 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -375,30 +375,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"); @@ -407,38 +416,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) @@ -448,14 +472,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"); @@ -464,6 +501,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 43d5fb3e50f5..3c9ee6a3e7b5 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 { @@ -295,7 +294,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. @@ -304,22 +314,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. @@ -328,8 +381,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. @@ -344,18 +423,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 2c14e1188699..517de1be87ef 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -307,44 +307,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"); @@ -353,72 +347,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) @@ -428,26 +402,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"); @@ -456,6 +428,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 1f1800a31284..9a8dc1c3b8b6 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -280,8 +280,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. @@ -290,12 +314,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. @@ -304,8 +348,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. @@ -335,8 +390,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 @@ -346,8 +427,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 5763cf7631ae..8123079d35cc 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs @@ -11,6 +11,7 @@ using Amazon.DynamoDBv2.DocumentModel; using Amazon.DynamoDBv2.DataModel; + namespace AWSSDK_DotNet.IntegrationTests.Tests.DynamoDB { public partial class DynamoDBTests : TestBase @@ -370,7 +371,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); @@ -380,7 +383,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); @@ -967,7 +972,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", }); @@ -978,7 +983,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 @@ -1000,7 +1005,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 @@ -1114,21 +1119,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 @@ -1144,7 +1149,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" @@ -1154,13 +1159,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 @@ -1170,7 +1175,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; } } } } From 4eea4d3f61aab3e6ff056113814911f22b7f6177 Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Mon, 5 Aug 2024 09:47:24 -0400 Subject: [PATCH 4/8] Create separate operation-specific configs for the Delete, Load, and Save Operations (#3387) --- .../DynamoDBv2/Custom/DataModel/Context.cs | 137 ++++---- .../Custom/DataModel/ContextInternal.cs | 3 +- .../Custom/DataModel/DeleteConfig.cs | 43 +++ .../Custom/DataModel/FromDocumentConfig.cs | 47 +++ .../Custom/DataModel/GetTargetTableConfig.cs | 35 ++ .../Custom/DataModel/IDynamoDBContext.cs | 54 +++- .../DynamoDBv2/Custom/DataModel/LoadConfig.cs | 54 ++++ .../DynamoDBv2/Custom/DataModel/SaveConfig.cs | 52 +++ .../Custom/DataModel/ToDocumentConfig.cs | 44 +++ .../Custom/DataModel/_async/Context.Async.cs | 300 ++++++------------ .../_async/IDynamoDBContext.Async.cs | 245 +++++++++++--- .../Custom/DataModel/_bcl/Context.Sync.cs | 264 ++++++--------- .../DataModel/_bcl/IDynamoDBContext.Sync.cs | 250 ++++++++++++--- .../DataModel/_netstandard/Context.Sync.cs | 21 +- .../_netstandard/IDynamoDBContext.Sync.cs | 15 + .../IntegrationTests/DataModelTests.cs | 30 +- .../DataModelOperationSpecificConfigTests.cs | 117 +++++++ 17 files changed, 1161 insertions(+), 550 deletions(-) create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/DeleteConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/FromDocumentConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/GetTargetTableConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/LoadConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/SaveConfig.cs create mode 100644 sdk/src/Services/DynamoDBv2/Custom/DataModel/ToDocumentConfig.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs index 80e9d1458b42..329ad6834b2f 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs @@ -475,11 +475,10 @@ public MultiTableTransactWrite CreateMultiTableTransactWrite(params TransactWrit #region Save/serialize - private void SaveHelper(T value, DynamoDBOperationConfig operationConfig) + private void SaveHelper(T value, DynamoDBFlatConfig flatConfig) { if (value == null) return; - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorage storage = ObjectToItemStorage(value, false, flatConfig); if (storage == null) return; @@ -503,16 +502,15 @@ private void SaveHelper(T value, DynamoDBOperationConfig operationConfig) } #if AWS_ASYNC_API - private async Task SaveHelperAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private async Task SaveHelperAsync(T value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { - await SaveHelperAsync(typeof(T), value, operationConfig, cancellationToken).ConfigureAwait(false); + await SaveHelperAsync(typeof(T), value, flatConfig, cancellationToken).ConfigureAwait(false); } - private async Task SaveHelperAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private async Task SaveHelperAsync(Type valueType, object value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { if (value == null) return; - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorage storage = ObjectToItemStorage(value, valueType, false, flatConfig); if (storage == null) return; @@ -537,24 +535,14 @@ await table.UpdateHelperAsync( } #endif - /// - /// Serializes an object to a Document. - /// - /// Type to serialize as. - /// Object to serialize. - /// Document with attributes populated from object. + /// public Document ToDocument(T value) { - return ToDocument(value, null); + return ToDocument(value, (ToDocumentConfig)null); } - /// - /// Serializes an object to a Document. - /// - /// Type to serialize as. - /// Object to serialize. - /// Config object which can be used to override the table used. - /// Document with attributes populated from object. + /// + [Obsolete("Use the ToDocument overload that takes ToDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to ToDocument.")] public Document ToDocument(T value, DynamoDBOperationConfig operationConfig) { if (value == null) return null; @@ -566,40 +554,48 @@ public Document ToDocument(T value, DynamoDBOperationConfig operationConfig) return storage.Document; } + /// + public Document ToDocument(T value, ToDocumentConfig toDocumentConfig) + { + if (value == null) return null; + + DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(toDocumentConfig?.ToDynamoDBOperationConfig(), Config); + ItemStorage storage = ObjectToItemStorage(value, false, flatConfig); + if (storage == null) return null; + + return storage.Document; + } + #endregion #region Load/deserialize - private T LoadHelper(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig) + private T LoadHelper(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig) { - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig); return LoadHelper(key, flatConfig, storageConfig); } #if AWS_ASYNC_API - private Task LoadHelperAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private Task LoadHelperAsync(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig); return LoadHelperAsync(key, flatConfig, storageConfig, cancellationToken); } #endif - private T LoadHelper(T keyObject, DynamoDBOperationConfig operationConfig) + private T LoadHelper(T keyObject, DynamoDBFlatConfig flatConfig) { - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); Key key = MakeKey(keyObject, storageConfig, flatConfig); return LoadHelper(key, flatConfig, storageConfig); } #if AWS_ASYNC_API - private Task LoadHelperAsync(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private Task LoadHelperAsync(T keyObject, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); Key key = MakeKey(keyObject, storageConfig, flatConfig); return LoadHelperAsync(key, flatConfig, storageConfig, cancellationToken); @@ -640,34 +636,27 @@ private async Task LoadHelperAsync(Key key, DynamoDBFlatConfig flatConfig, } #endif - /// - /// Deserializes a document to an instance of type T. - /// - /// Type to populate. - /// Document with properties to use. - /// - /// Object of type T, populated with properties from the document. - /// + /// public T FromDocument(Document document) { - return FromDocument(document, null); + return FromDocument(document, (FromDocumentConfig)null); } - /// - /// Deserializes a document to an instance of type T. - /// - /// Type to populate. - /// Document with properties to use. - /// Config object which can be used to override the table used. - /// - /// Object of type T, populated with properties from the document. - /// + /// + [Obsolete("Use the FromDocument overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocument.")] public T FromDocument(Document document, DynamoDBOperationConfig operationConfig) { DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, Config); return FromDocumentHelper(document, flatConfig); } + /// + public T FromDocument(Document document, FromDocumentConfig fromDocumentConfig) + { + DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(fromDocumentConfig?.ToDynamoDBOperationConfig(), Config); + return FromDocumentHelper(document, flatConfig); + } + internal T FromDocumentHelper(Document document, DynamoDBFlatConfig flatConfig) { ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); @@ -677,28 +666,14 @@ internal T FromDocumentHelper(Document document, DynamoDBFlatConfig flatConfi return instance; } - /// - /// Deserializes a collections of documents to a collection of instances of type T. - /// - /// Type to populate. - /// Documents to deserialize. - /// - /// Collection of items of type T, each populated with properties from a corresponding document. - /// + /// public IEnumerable FromDocuments(IEnumerable documents) { - return FromDocuments(documents, null); + return FromDocuments(documents, (FromDocumentConfig)null); } - /// - /// Deserializes a collections of documents to a collection of instances of type T. - /// - /// Type to populate. - /// Documents to deserialize. - /// Config object which can be used to override the table used. - /// - /// Collection of items of type T, each populated with properties from a corresponding document. - /// + /// + [Obsolete("Use the FromDocuments overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocuments.")] public IEnumerable FromDocuments(IEnumerable documents, DynamoDBOperationConfig operationConfig) { foreach (var document in documents) @@ -708,6 +683,16 @@ public IEnumerable FromDocuments(IEnumerable documents, DynamoDB } } + /// + public IEnumerable FromDocuments(IEnumerable documents, FromDocumentConfig fromDocumentConfig) + { + foreach (var document in documents) + { + T item = FromDocument(document, fromDocumentConfig); + yield return item; + } + } + internal IEnumerable FromDocumentsHelper(IEnumerable documents, DynamoDBFlatConfig flatConfig) { foreach (var document in documents) @@ -721,33 +706,30 @@ internal IEnumerable FromDocumentsHelper(IEnumerable documents, #region Delete - private void DeleteHelper(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig) + private void DeleteHelper(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig) { - DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); - ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(config); - Key key = MakeKey(hashKey, rangeKey, storageConfig, config); + ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); + Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig); - Table table = GetTargetTable(storageConfig, config); + Table table = GetTargetTable(storageConfig, flatConfig); table.DeleteHelper(key, null); } #if AWS_ASYNC_API - private Task DeleteHelperAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private Task DeleteHelperAsync(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { - DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config); - ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(config); - Key key = MakeKey(hashKey, rangeKey, storageConfig, config); + ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(flatConfig); + Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig); - Table table = GetTargetTable(storageConfig, config); + Table table = GetTargetTable(storageConfig, flatConfig); return table.DeleteHelperAsync(key, null, cancellationToken); } #endif - private void DeleteHelper(T value, DynamoDBOperationConfig operationConfig) + private void DeleteHelper(T value, DynamoDBFlatConfig flatConfig) { if (value == null) throw new ArgumentNullException("value"); - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); flatConfig.IgnoreNullValues = true; ItemStorage storage = ObjectToItemStorage(value, true, flatConfig); if (storage == null) return; @@ -770,11 +752,10 @@ private void DeleteHelper(T value, DynamoDBOperationConfig operationConfig) private static readonly Task CompletedTask = Task.FromResult(null); - private Task DeleteHelperAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) + private Task DeleteHelperAsync(T value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken) { if (value == null) throw new ArgumentNullException("value"); - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); flatConfig.IgnoreNullValues = true; ItemStorage storage = ObjectToItemStorage(value, true, flatConfig); if (storage == null) return CompletedTask; diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs index 3b8199cc050d..447c52c65dcd 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextInternal.cs @@ -121,10 +121,9 @@ internal static Expression CreateConditionExpressionForVersion(ItemStorage stora #region Table methods // Retrieves the target table for the specified type - private Table GetTargetTableInternal(DynamoDBOperationConfig operationConfig) + private Table GetTargetTableInternal(DynamoDBFlatConfig flatConfig) { Type type = typeof(T); - DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config); ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(type, flatConfig); Table table = GetTargetTable(storageConfig, flatConfig, Table.DynamoDBConsumer.DocumentModel); return table; diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/DeleteConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/DeleteConfig.cs new file mode 100644 index 000000000000..4064195cd5cc --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/DeleteConfig.cs @@ -0,0 +1,43 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the Delete 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 DeleteConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.SkipVersionCheck = SkipVersionCheck; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/FromDocumentConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/FromDocumentConfig.cs new file mode 100644 index 000000000000..454ebeb2aaa2 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/FromDocumentConfig.cs @@ -0,0 +1,47 @@ +/* + * 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; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the FromDocument 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 FromDocumentConfig : 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/DataModel/GetTargetTableConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/GetTargetTableConfig.cs new file mode 100644 index 000000000000..795ed6020c09 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/GetTargetTableConfig.cs @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the GetTargetTable 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 GetTargetTableConfig : BaseOperationConfig + { + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs index 17868bbf21f2..19081d794dd5 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/IDynamoDBContext.cs @@ -47,53 +47,75 @@ public partial interface IDynamoDBContext : IDisposable #region Save/serialize /// - /// Serializes an object to a Document. + /// Serializes an object to a . /// /// Type to serialize as. /// Object to serialize. - /// Document with attributes populated from object. + /// with attributes populated from object. Document ToDocument(T value); /// - /// Serializes an object to a Document. + /// Serializes an object to a . /// /// Type to serialize as. /// Object to serialize. /// Config object which can be used to override the table used. - /// Document with attributes populated from object. + /// with attributes populated from object. + [Obsolete("Use the ToDocument overload that takes ToDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to ToDocument.")] Document ToDocument(T value, DynamoDBOperationConfig operationConfig); + /// + /// Serializes an object to a . + /// + /// Type to serialize as. + /// Object to serialize. + /// Config object that can be used to override properties on the table's context for this request. + /// with attributes populated from object. + Document ToDocument(T value, ToDocumentConfig toDocumentConfig); + #endregion #region Load/deserialize /// - /// Deserializes a document to an instance of type T. + /// Deserializes a to an instance of type T. /// /// Type to populate. - /// Document with properties to use. + /// with properties to use. /// /// Object of type T, populated with properties from the document. /// T FromDocument(Document document); /// - /// Deserializes a document to an instance of type T. + /// Deserializes a to an instance of type T. /// /// Type to populate. - /// Document with properties to use. + /// with properties to use. /// Config object which can be used to override the table used. /// /// Object of type T, populated with properties from the document. /// + [Obsolete("Use the FromDocument overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocument.")] + T FromDocument(Document document, DynamoDBOperationConfig operationConfig); + /// + /// Deserializes a to an instance of type T. + /// + /// Type to populate. + /// with properties to use. + /// Config object that can be used to override properties on the table's context for this request. + /// + /// Object of type T, populated with properties from the document. + /// + T FromDocument(Document document, FromDocumentConfig fromDocumentConfig); /// /// Deserializes a collections of documents to a collection of instances of type T. /// /// Type to populate. - /// Documents to deserialize. + /// Collection of objects to deserialize. /// /// Collection of items of type T, each populated with properties from a corresponding document. /// @@ -103,13 +125,25 @@ public partial interface IDynamoDBContext : IDisposable /// Deserializes a collections of documents to a collection of instances of type T. /// /// Type to populate. - /// Documents to deserialize. + /// Collection of objects to deserialize. /// Config object which can be used to override the table used. /// /// Collection of items of type T, each populated with properties from a corresponding document. /// + [Obsolete("Use the FromDocuments overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocuments.")] IEnumerable FromDocuments(IEnumerable documents, DynamoDBOperationConfig operationConfig); + /// + /// Deserializes a collections of documents to a collection of instances of type T. + /// + /// Type to populate. + /// Collection of objects to deserialize. + /// Config object that can be used to override properties on the table's context for this request. + /// + /// Collection of items of type T, each populated with properties from a corresponding document. + /// + IEnumerable FromDocuments(IEnumerable documents, FromDocumentConfig fromDocumentConfig); + #endregion #region BatchGet diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/LoadConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/LoadConfig.cs new file mode 100644 index 000000000000..9ca0f36e837e --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/LoadConfig.cs @@ -0,0 +1,54 @@ +/* + * 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; + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the Load 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 LoadConfig : BaseOperationConfig + { + /// + /// Property that directs to use consistent reads. + /// If property is not set, behavior defaults to non-consistent reads. + /// + 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.ConsistentRead = ConsistentRead; + config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/SaveConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/SaveConfig.cs new file mode 100644 index 000000000000..5592a43c3531 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/SaveConfig.cs @@ -0,0 +1,52 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the Save 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 SaveConfig : BaseOperationConfig + { + /// + /// 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; } + + /// + /// Directs to ignore null values when + /// converting an object to a DynamoDB item. If the property is false + /// (or not set), null values will be interpreted as directives to + /// delete the specific attributes on the DynamoDB item. + /// + public bool? IgnoreNullValues { get; set; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.SkipVersionCheck = SkipVersionCheck; + config.IgnoreNullValues = IgnoreNullValues; + + return config; + } + } +} diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/ToDocumentConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ToDocumentConfig.cs new file mode 100644 index 000000000000..be24bac29255 --- /dev/null +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/ToDocumentConfig.cs @@ -0,0 +1,44 @@ +/* + * 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. + */ + +namespace Amazon.DynamoDBv2.DataModel +{ + /// + /// Input for the ToDocument 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 ToDocumentConfig : BaseOperationConfig + { + /// + /// Directs to ignore null values when + /// converting an object to a DynamoDB item. If the property is false + /// (or not set), null values will be interpreted as directives to + /// delete the specific attributes on the DynamoDB item. + /// + public bool? IgnoreNullValues { get; set; } + + /// + internal override DynamoDBOperationConfig ToDynamoDBOperationConfig() + { + var config = base.ToDynamoDBOperationConfig(); + config.IgnoreNullValues = IgnoreNullValues; + + 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 f65ff104d0fc..5a320690d12c 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs @@ -33,256 +33,164 @@ public partial class DynamoDBContext : IDynamoDBContext { #region Save async - /// - /// Initiates the asynchronous execution of the Save operation. - /// - /// - /// Type to save as. - /// Object 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 SaveAsync(T value, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task SaveAsync(T value, CancellationToken cancellationToken = default) { - return SaveHelperAsync(value, null, cancellationToken); + return SaveHelperAsync(value, new DynamoDBFlatConfig(null, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Save operation. - /// - /// - /// Type to save as. - /// Object to save. - /// Overriding configuration. - /// 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 SaveAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + [Obsolete("Use the SaveAsync overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to SaveAsync.")] + public Task SaveAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) { - return SaveHelperAsync(value, operationConfig, cancellationToken); + return SaveHelperAsync(value, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Save operation. - /// - /// - /// Type of the Object to save. - /// Object 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 SaveAsync(Type valueType, object value, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task SaveAsync(T value, SaveConfig saveConfig, CancellationToken cancellationToken = default) { - return SaveHelperAsync(valueType, value, null, cancellationToken); + return SaveHelperAsync(value, new DynamoDBFlatConfig(saveConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Save operation. - /// - /// - /// Type of the Object to save. - /// Object to save. - /// Overriding configuration. - /// 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 SaveAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task SaveAsync(Type valueType, object value, CancellationToken cancellationToken = default) + { + return SaveHelperAsync(valueType, value, new DynamoDBFlatConfig(null, Config), cancellationToken); + } + + /// + [Obsolete("Use the SaveAsync overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to SaveAsync.")] + public Task SaveAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) + { + return SaveHelperAsync(valueType, value, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); + } + + /// + public Task SaveAsync(Type valueType, object value, SaveConfig saveConfig, CancellationToken cancellationToken = default) { - return SaveHelperAsync(valueType, value, operationConfig, cancellationToken); + return SaveHelperAsync(valueType, value, new DynamoDBFlatConfig(saveConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } #endregion #region Load async - /// - /// Loads an object from DynamoDB for the given hash key. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(object hashKey, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task LoadAsync(object hashKey, CancellationToken cancellationToken = default) { - return LoadHelperAsync(hashKey, null, null, cancellationToken); + return LoadHelperAsync(hashKey, null, new DynamoDBFlatConfig(null, Config), cancellationToken); } - /// - /// Loads an object from DynamoDB for the given hash key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. - /// Hash key element of the target item. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + public Task LoadAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) { - return LoadHelperAsync(hashKey, null, operationConfig, cancellationToken); + return LoadHelperAsync(hashKey, null, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); } - /// - /// Loads an object from DynamoDB for the given hash-and-range primary key. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Range key element of the target item. - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task LoadAsync(object hashKey, LoadConfig loadConfig, CancellationToken cancellationToken = default) { - return LoadHelperAsync(hashKey, rangeKey, null, cancellationToken); + return LoadHelperAsync(hashKey, null, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } - /// - /// Loads an object from DynamoDB for the given hash-and-range primary key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Range key element of the target item. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task LoadAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default) { - return LoadHelperAsync(hashKey, rangeKey, operationConfig, cancellationToken); + return LoadHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(null, Config), cancellationToken); } - /// - /// Loads an object from DynamoDB for the given key. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// A partially-specified instance, where the - /// hash/range properties are equal to the key of the item you - /// want to load. - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(T keyObject, CancellationToken cancellationToken = default(CancellationToken)) + /// + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + public Task LoadAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) { - return LoadHelperAsync(keyObject, null, cancellationToken); + return LoadHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); } - /// - /// Loads an object from DynamoDB for the given key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// A partially-specified instance, where the - /// hash/range properties are equal to the key of the item you - /// want to load. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// Token which can be used to cancel the task. - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - public Task LoadAsync(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task LoadAsync(object hashKey, object rangeKey, LoadConfig loadConfig, CancellationToken cancellationToken = default) { - return LoadHelperAsync(keyObject, operationConfig, cancellationToken); + return LoadHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); + } + + /// + public Task LoadAsync(T keyObject, CancellationToken cancellationToken = default) + { + return LoadHelperAsync(keyObject, new DynamoDBFlatConfig(null, Config), cancellationToken); + } + + /// + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + public Task LoadAsync(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) + { + return LoadHelperAsync(keyObject, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); + } + + /// + public Task LoadAsync(T keyObject, LoadConfig loadConfig, CancellationToken cancellationToken = default) + { + return LoadHelperAsync(keyObject, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } #endregion #region Delete async - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Object 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 DeleteAsync(T value, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task DeleteAsync(T value, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(value, null, cancellationToken); + return DeleteHelperAsync(value, new DynamoDBFlatConfig(null, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Object to delete. - /// Overriding configuration. - /// 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 DeleteAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + public Task DeleteAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(value, operationConfig, cancellationToken); + return DeleteHelperAsync(value, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Hash key element of the object 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 DeleteAsync(object hashKey, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task DeleteAsync(T value, DeleteConfig deleteConfig, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(hashKey, null, null, cancellationToken); + return DeleteHelperAsync(value, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Config object which can be used to override that table used. - /// 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 DeleteAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task DeleteAsync(object hashKey, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(hashKey, null, operationConfig, cancellationToken); + return DeleteHelperAsync(hashKey, null, new DynamoDBFlatConfig(null, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Range key element of the object 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 DeleteAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default(CancellationToken)) + /// + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + public Task DeleteAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(hashKey, rangeKey, null, cancellationToken); + return DeleteHelperAsync(hashKey, null, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); } - /// - /// Initiates the asynchronous execution of the Delete operation. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Range key element of the object to delete. - /// Config object which can be used to override that table used. - /// 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 DeleteAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)) + /// + public Task DeleteAsync(object hashKey, DeleteConfig deleteConfig, CancellationToken cancellationToken = default) + { + return DeleteHelperAsync(hashKey, null, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); + } + + /// + public Task DeleteAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default) + { + return DeleteHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(null, Config), cancellationToken); + } + + /// + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + public Task DeleteAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default) + { + return DeleteHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(operationConfig, Config), cancellationToken); + } + + /// + public Task DeleteAsync(object hashKey, object rangeKey, DeleteConfig deleteConfig, CancellationToken cancellationToken = default) { - return DeleteHelperAsync(hashKey, rangeKey, operationConfig, cancellationToken); + return DeleteHelperAsync(hashKey, rangeKey, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config), cancellationToken); } #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 3c9ee6a3e7b5..030ee738d2fc 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -31,46 +31,82 @@ partial interface IDynamoDBContext #region Save async /// - /// Initiates the asynchronous execution of the Save operation. - /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// Type to save as. /// Object 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. - Task SaveAsync(T value, CancellationToken cancellationToken = default(CancellationToken)); + Task SaveAsync(T value, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Save operation. - /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// Type to save as. /// Object to save. /// Overriding configuration. /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task SaveAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the SaveAsync overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to SaveAsync.")] + Task SaveAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Save operation. - /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to save as. + /// Object to save. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task SaveAsync(T value, SaveConfig saveConfig, CancellationToken cancellationToken = default); + + /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// Type of the Object to save. /// Object 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. - Task SaveAsync(Type valueType, object value, CancellationToken cancellationToken = default(CancellationToken)); + Task SaveAsync(Type valueType, object value, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Save operation. - /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// Type of the Object to save. /// Object to save. /// Overriding configuration. /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task SaveAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the SaveAsync overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to SaveAsync.")] + Task SaveAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); + + /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of the Object to save. + /// Object to save. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task SaveAsync(Type valueType, object value, SaveConfig saveConfig, CancellationToken cancellationToken = default); #endregion @@ -87,10 +123,10 @@ partial interface IDynamoDBContext /// Hash key element of the target item. /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(object hashKey, CancellationToken cancellationToken = default(CancellationToken)); + Task LoadAsync(object hashKey, CancellationToken cancellationToken = default); /// - /// Loads an object from DynamoDB for the given hash key and using the given config. + /// Loads an object from DynamoDB for the given hash key. /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -103,10 +139,11 @@ partial interface IDynamoDBContext /// /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + Task LoadAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); /// - /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// Loads an object from DynamoDB for the given hash key. /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -114,13 +151,26 @@ partial interface IDynamoDBContext /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least /// one public field/property with DynamoDBHashKeyAttribute. /// Hash key element of the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task LoadAsync(object hashKey, LoadConfig loadConfig, CancellationToken cancellationToken = default); + + /// + /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Hash key element of the target item. /// Range key element of the target item. /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default(CancellationToken)); + Task LoadAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default); /// - /// Loads an object from DynamoDB for the given hash-and-range primary key and using the given config. + /// Loads an object from DynamoDB for the given hash-and-range primary key. /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -135,25 +185,50 @@ partial interface IDynamoDBContext /// /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + Task LoadAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); + + /// + /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// + /// + /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. + + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Hash key element of the target item. + /// Range key element of the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task LoadAsync(object hashKey, object rangeKey, LoadConfig loadConfig, CancellationToken cancellationToken = default); /// /// Loads an object from DynamoDB for the given key. + /// The keyObject is a partially-specified instance, where the + /// hash/range properties are equal to the key of the item you + /// want to load. /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. /// /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least /// one public field/property with DynamoDBHashKeyAttribute. - /// A partially-specified instance, where the - /// hash/range properties are equal to the key of the item you - /// want to load. + /// Key of the target item. /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(T keyObject, CancellationToken cancellationToken = default(CancellationToken)); + Task LoadAsync(T keyObject, CancellationToken cancellationToken = default); /// - /// Loads an object from DynamoDB for the given key and using the given config. + /// Loads an object from DynamoDB for the given key. + /// The keyObject is a partially-specified instance, where the + /// hash/range properties are equal to the key of the item you + /// want to load. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -169,70 +244,166 @@ partial interface IDynamoDBContext /// /// Token which can be used to cancel the task. /// Object of type T, populated with the properties of the item loaded from DynamoDB. - Task LoadAsync(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the LoadAsync overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to LoadAsync.")] + Task LoadAsync(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); + + /// + /// Loads an object from DynamoDB for the given key. + /// The keyObject is a partially-specified instance, where the + /// hash/range properties are equal to the key of the item you + /// want to load. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Key of the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task LoadAsync(T keyObject, LoadConfig loadConfig, CancellationToken cancellationToken = default); #endregion #region Delete async /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to given object. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Object 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. - Task DeleteAsync(T value, CancellationToken cancellationToken = default(CancellationToken)); + Task DeleteAsync(T value, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to given object. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Object to delete. /// Overriding configuration. /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task DeleteAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + Task DeleteAsync(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to given object. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Object to delete. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task DeleteAsync(T value, DeleteConfig deleteConfig, CancellationToken cancellationToken = default); + + /// + /// Deletes an item in DynamoDB corresponding to given hash key. + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object 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. - Task DeleteAsync(object hashKey, CancellationToken cancellationToken = default(CancellationToken)); + Task DeleteAsync(object hashKey, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to given hash key. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Config object which can be used to override that table used. /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task DeleteAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + Task DeleteAsync(object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to given hash key. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Hash key element of the object to delete. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task DeleteAsync(object hashKey, DeleteConfig deleteConfig, CancellationToken cancellationToken = default); + + /// + /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Range key element of the object 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. - Task DeleteAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default(CancellationToken)); + Task DeleteAsync(object hashKey, object rangeKey, CancellationToken cancellationToken = default); /// - /// Initiates the asynchronous execution of the Delete operation. + /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Range key element of the object to delete. /// Config object which can be used to override that table used. /// Token which can be used to cancel the task. /// A Task that can be used to poll or wait for results, or both. - Task DeleteAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default(CancellationToken)); + [Obsolete("Use the DeleteAsync overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to DeleteAsync.")] + Task DeleteAsync(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken = default); + + /// + /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Hash key element of the object to delete. + /// Range key element of the object to delete. + /// Config object that can be used to override properties on the table's context for this request. + /// Token which can be used to cancel the task. + /// A Task that can be used to poll or wait for results, or both. + Task DeleteAsync(object hashKey, object rangeKey, DeleteConfig deleteConfig, CancellationToken cancellationToken = default); #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 517de1be87ef..98a57588013a 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs @@ -26,219 +26,146 @@ public partial class DynamoDBContext : IDynamoDBContext { #region Save/serialize - /// - /// Saves an object to DynamoDB using passed-in configs. - /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type to save as. - /// Object to save. - /// Overriding configuration. + /// + public void Save(T value) + { + SaveHelper(value, new DynamoDBFlatConfig(null, Config)); + } + + /// + [Obsolete("Use the Save overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Save.")] public void Save(T value, DynamoDBOperationConfig operationConfig = null) { - SaveHelper(value, operationConfig); + SaveHelper(value, new DynamoDBFlatConfig(operationConfig, Config)); + } + + /// + public void Save(T value, SaveConfig saveConfig) + { + SaveHelper(value, new DynamoDBFlatConfig(saveConfig?.ToDynamoDBOperationConfig(), Config)); } #endregion #region Load/deserialize - /// - /// Loads an object from DynamoDB for the given hash key. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - /// + /// public T Load(object hashKey) { - return LoadHelper(hashKey, null, null); + return LoadHelper(hashKey, null, new DynamoDBFlatConfig(null, Config)); } - /// - /// Loads an object from DynamoDB for the given hash key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - /// + /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] public T Load(object hashKey, DynamoDBOperationConfig operationConfig) { - return LoadHelper(hashKey, null, operationConfig); + return LoadHelper(hashKey, null, new DynamoDBFlatConfig(operationConfig, Config)); } - /// - /// Loads an object from DynamoDB for the given hash-and-range primary key. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Range key element of the target item. - /// - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - /// + /// + public T Load(object hashKey, LoadConfig loadConfig) + { + return LoadHelper(hashKey, null, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config)); + } + + /// public T Load(object hashKey, object rangeKey) { - return LoadHelper(hashKey, rangeKey, null); + return LoadHelper(hashKey, rangeKey, new DynamoDBFlatConfig(null, Config)); } - /// - /// Loads an object from DynamoDB for the given hash-and-range primary key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// Hash key element of the target item. - /// Range key element of the target item. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - /// + /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] public T Load(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig) { - return LoadHelper(hashKey, rangeKey, operationConfig); + return LoadHelper(hashKey, rangeKey, new DynamoDBFlatConfig(operationConfig, Config)); } - /// - /// Loads an object from DynamoDB for the given key and using the given config. - /// - /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// - /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// A partially-specified instance, where the - /// hash/range properties are equal to the key of the item you - /// want to load. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// - /// - /// Object of type T, populated with the properties of the item loaded from DynamoDB. - /// + /// + public T Load(object hashKey, object rangeKey, LoadConfig loadConfig) + { + return LoadHelper(hashKey, rangeKey, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config)); + } + + /// + public T Load(T keyObject) + { + return LoadHelper(keyObject, new DynamoDBFlatConfig(null, Config)); + } + + /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] public T Load(T keyObject, DynamoDBOperationConfig operationConfig = null) { - return LoadHelper(keyObject, operationConfig); + return LoadHelper(keyObject, new DynamoDBFlatConfig(operationConfig, Config)); + } + + /// + public T Load(T keyObject, LoadConfig loadConfig) + { + return LoadHelper(keyObject, new DynamoDBFlatConfig(loadConfig?.ToDynamoDBOperationConfig(), Config)); } #endregion #region Delete - /// - /// Deletes an item in DynamoDB corresponding to given object. - /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// If SkipVersionCheck=false, will check version of object before deleting. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. - /// Object to delete. + /// public void Delete(T value) { - DeleteHelper(value, null); + DeleteHelper(value, new DynamoDBFlatConfig(null, Config)); } - /// - /// Deletes an item in DynamoDB corresponding to given object. - /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// If SkipVersionCheck=false, will check version of object before deleting. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. - /// Object to delete. - /// Overriding configuration. + /// + [Obsolete("Use the Delete overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] public void Delete(T value, DynamoDBOperationConfig operationConfig) { - DeleteHelper(value, operationConfig); + DeleteHelper(value, new DynamoDBFlatConfig(operationConfig, Config)); } - /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. + /// + public void Delete(T value, DeleteConfig deleteConfig) + { + DeleteHelper(value, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config)); + } + + /// /// Hash key element of the object to delete. public void Delete(object hashKey) { - DeleteHelper(hashKey, null, null); + DeleteHelper(hashKey, null, new DynamoDBFlatConfig(null, Config)); } - /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Config object which can be used to override that table used. + /// + [Obsolete("Use the Delete overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] public void Delete(object hashKey, DynamoDBOperationConfig operationConfig) { - DeleteHelper(hashKey, null, operationConfig); + DeleteHelper(hashKey, null, new DynamoDBFlatConfig(operationConfig, Config)); } - /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Range key element of the object to delete. + /// + public void Delete(object hashKey, DeleteConfig deleteConfig) + { + DeleteHelper(hashKey, null, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config)); + } + + /// public void Delete(object hashKey, object rangeKey) { - DeleteHelper(hashKey, rangeKey, null); + DeleteHelper(hashKey, rangeKey, new DynamoDBFlatConfig(null, Config)); } - /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. - /// - /// Type of object. - /// Hash key element of the object to delete. - /// Range key element of the object to delete. - /// Config object which can be used to override that table used. + /// + [Obsolete("Use the Delete overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] public void Delete(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig) { - DeleteHelper(hashKey, rangeKey, operationConfig); + DeleteHelper(hashKey, rangeKey, new DynamoDBFlatConfig(operationConfig, Config)); + } + + /// + public void Delete(object hashKey, object rangeKey, DeleteConfig deleteConfig) + { + DeleteHelper(hashKey, rangeKey, new DynamoDBFlatConfig(deleteConfig?.ToDynamoDBOperationConfig(), Config)); } #endregion @@ -441,14 +368,23 @@ public IEnumerable FromQuery(QueryOperationConfig queryConfig, FromQueryCo #region Table methods - /// - /// Retrieves the target table for the specified type - /// - /// Type to retrieve table for - /// Table object + /// + public Table 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) { - return GetTargetTableInternal(operationConfig); + return GetTargetTableInternal(new DynamoDBFlatConfig(operationConfig, Config)); + } + + /// + public Table GetTargetTable(GetTargetTableConfig getTargetTableConfig) + { + return GetTargetTableInternal(new DynamoDBFlatConfig(getTargetTableConfig?.ToDynamoDBOperationConfig(), Config)); } #endregion 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 9a8dc1c3b8b6..dc4d0e509146 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -30,23 +30,48 @@ partial interface IDynamoDBContext #region Save/serialize /// - /// Saves an object to DynamoDB using passed-in configs. + /// Saves an object to DynamoDB. /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. + /// The type must be marked up with and at least + /// one public field/property with . /// /// Type to save as. /// Object to save. - /// Overriding configuration. + void Save(T value); + + /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to save as. + /// Object to save. + /// Config object that can be used to override properties on the table's context for this request. + [Obsolete("Use the Save overload that takes SaveConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Save.")] void Save(T value, DynamoDBOperationConfig operationConfig = null); + /// + /// Saves an object to DynamoDB. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to save as. + /// Object to save. + /// Config object that can be used to override properties on the table's context for this request + void Save(T value, SaveConfig saveConfig); + + #endregion #region Load/deserialize /// /// Loads an object from DynamoDB for the given hash key. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -60,7 +85,10 @@ partial interface IDynamoDBContext T Load(object hashKey); /// - /// Loads an object from DynamoDB for the given hash key and using the given config. + /// Loads an object from DynamoDB for the given hash key. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -75,10 +103,14 @@ partial interface IDynamoDBContext /// /// Object of type T, populated with the properties of the item loaded from DynamoDB. /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] T Load(object hashKey, DynamoDBOperationConfig operationConfig); /// - /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// Loads an object from DynamoDB for the given hash key. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -86,6 +118,20 @@ partial interface IDynamoDBContext /// Type to populate. It must be marked up with DynamoDBTableAttribute and at least /// one public field/property with DynamoDBHashKeyAttribute. /// Hash key element of the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// + /// Object of type T, populated with properties of item loaded from DynamoDB. + /// + T Load(object hashKey, LoadConfig loadConfig); + + /// + /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Hash key element of the target item. /// Range key element of the target item. /// /// Object of type T, populated with the properties of the item loaded from DynamoDB. @@ -93,7 +139,10 @@ partial interface IDynamoDBContext T Load(object hashKey, object rangeKey); /// - /// Loads an object from DynamoDB for the given hash-and-range primary key and using the given config. + /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// + /// The type must be marked up with and at least + /// one public field/property with . /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -109,10 +158,26 @@ partial interface IDynamoDBContext /// /// Object of type T, populated with the properties of the item loaded from DynamoDB. /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] T Load(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig); /// - /// Loads an object from DynamoDB for the given key and using the given config. + /// Loads an object from DynamoDB for the given hash-and-range primary key. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Hash key element of the target item. + /// Range key element of the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// + /// Object of type T, populated with properties of item loaded from DynamoDB. + /// + T Load(object hashKey, object rangeKey, LoadConfig loadConfig); + + /// + /// Loads an object from DynamoDB for the given key. /// /// /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. @@ -121,75 +186,143 @@ partial interface IDynamoDBContext /// one public field/property with DynamoDBHashKeyAttribute. /// A partially-specified instance, where the /// hash/range properties are equal to the key of the item you - /// want to load. - /// Overrides the DynamoDBContextConfig on the context object. - /// Note that its IndexName does not influence which object is loaded. Rather - /// the item's primary key for the table must be specified. - /// + /// want to load. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Key object defining the the target item. + /// + /// Object of type T, populated with properties of item loaded from DynamoDB. + /// + T Load(T keyObject); + + /// + /// Loads an object from DynamoDB for the given key. + /// The keyObject is a partially-specified instance, where the + /// hash/range properties are equal to the key of the item you + /// want to load. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Key object defining the the target item. + /// Overriding configuration. /// /// Object of type T, populated with the properties of the item loaded from DynamoDB. /// + [Obsolete("Use the Load overload that takes LoadConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Load.")] T Load(T keyObject, DynamoDBOperationConfig operationConfig = null); + /// + /// Loads an object from DynamoDB for the given key. + /// The keyObject is a partially-specified instance, where the + /// hash/range properties are equal to the key of the item you + /// want to load. + /// + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type to populate. + /// Key object defining the the target item. + /// Config object that can be used to override properties on the table's context for this request. + /// + /// Object of type T, populated with properties of item loaded from DynamoDB. + /// + T Load(T keyObject, LoadConfig loadConfig); + #endregion #region Delete /// /// Deletes an item in DynamoDB corresponding to given object. - /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// If SkipVersionCheck=false, will check version of object before deleting. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Object to delete. void Delete(T value); /// /// Deletes an item in DynamoDB corresponding to given object. - /// - /// Passed-in config overrides DynamoDBContextConfig on the context. - /// If SkipVersionCheck=false, will check version of object before deleting. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Object to delete. /// Overriding configuration. + [Obsolete("Use the Delete overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] void Delete(T value, DynamoDBOperationConfig operationConfig); /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. + /// Deletes an item in DynamoDB corresponding to given object. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Object to delete. + /// Config object that can be used to override properties on the table's context for this request. + void Delete(T value, DeleteConfig deleteConfig); + + /// + /// Deletes an item in DynamoDB corresponding to given hash key + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. void Delete(object hashKey); /// - /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. + /// Deletes an item in DynamoDB corresponding to given hash key /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Config object which can be used to override that table used. + [Obsolete("Use the Delete overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] void Delete(object hashKey, DynamoDBOperationConfig operationConfig); + /// + /// Deletes an item in DynamoDB corresponding to given hash key. + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Hash key element of the object to delete. + /// Config object that can be used to override properties on the table's context for this request. + void Delete(object hashKey, DeleteConfig deleteConfig); + /// /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Range key element of the object to delete. @@ -197,17 +330,33 @@ partial interface IDynamoDBContext /// /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. - /// - /// No version check is done prior to delete. - /// Type must be marked up with DynamoDBTableAttribute and at least - /// one public field/property with DynamoDBHashKeyAttribute. /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// /// Type of object. /// Hash key element of the object to delete. /// Range key element of the object to delete. /// Config object which can be used to override that table used. + [Obsolete("Use the Delete overload that takes DeleteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to Delete.")] void Delete(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig); + /// + /// Deletes an item in DynamoDB corresponding to a given hash-and-range primary key. + /// + /// + /// If SkipVersionCheck if false, it will check the version of object before deleting. + /// The type must be marked up with and at least + /// one public field/property with . + /// + /// Type of object. + /// Hash key element of the object to delete. + /// Range key element of the object to delete. + /// Config object that can be used to override properties on the table's context for this request. + void Delete(object hashKey, object rangeKey, DeleteConfig deleteConfig); + #endregion #region BatchGet @@ -450,8 +599,25 @@ partial interface IDynamoDBContext /// /// Type to retrieve table for /// Table object + Table GetTargetTable(); + + /// + /// Retrieves the target table for the specified type + /// + /// Type to retrieve table for + /// 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); + /// + /// Retrieves the target table for the specified type + /// + /// 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); + #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 bd8adb6f9c8a..085925e38fa1 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/Context.Sync.cs @@ -26,14 +26,23 @@ public partial class DynamoDBContext : IDynamoDBContext { #region Table methods - /// - /// Retrieves the target table for the specified type - /// - /// Type to retrieve table for - /// Table object + /// + public Table 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) { - return GetTargetTableInternal(operationConfig); + return GetTargetTableInternal(new DynamoDBFlatConfig(operationConfig, Config)); + } + + /// + public Table GetTargetTable(GetTargetTableConfig getTargetTableConfig) + { + return GetTargetTableInternal(new DynamoDBFlatConfig(getTargetTableConfig?.ToDynamoDBOperationConfig(), Config)); } #endregion 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 ac9336048359..48a267e7636a 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_netstandard/IDynamoDBContext.Sync.cs @@ -34,8 +34,23 @@ partial interface IDynamoDBContext /// /// Type to retrieve table for /// Table object + Table GetTargetTable(); + + /// + /// Retrieves the target table for the specified type + /// + /// 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); + /// + /// Retrieves the target table for the specified type + /// + /// Type to retrieve table for + /// Table object + Table GetTargetTable(GetTargetTableConfig getTargetTableConfig); + #endregion } } diff --git a/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs b/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs index 8123079d35cc..078ea6d7e3a7 100644 --- a/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs +++ b/sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs @@ -359,7 +359,7 @@ public void TestContext_RetrieveDateTimeInUtc_OperationConfig(bool retrieveDateT var expectedCurrTime = retrieveDateTimeInUtc ? currTime.ToUniversalTime() : currTime.ToLocalTime(); // Load - var storedEmployee = Context.Load(employee.CreationTime, employee.Name, operationConfig); + var storedEmployee = Context.Load(employee.CreationTime, employee.Name, new LoadConfig { RetrieveDateTimeInUtc = retrieveDateTimeInUtc}); Assert.IsNotNull(storedEmployee); ApproximatelyEqual(expectedCurrTime, storedEmployee.CreationTime); ApproximatelyEqual(expectedCurrTime, storedEmployee.EpochDate2); @@ -606,8 +606,8 @@ private void TestContextConversions() }; { - var docV1 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV1 }); - var docV2 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV2 }); + var docV1 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV1 }); + var docV2 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV2 }); VerifyConversions(docV1, docV2); } @@ -625,7 +625,7 @@ private void TestContextConversions() using (var contextV1 = new DynamoDBContext(Client, new DynamoDBContextConfig { Conversion = conversionV1 })) { contextV1.Save(product); - contextV1.Save(product, new DynamoDBOperationConfig { Conversion = conversionV2 }); + contextV1.Save(product, new SaveConfig { Conversion = conversionV2 }); } } @@ -639,8 +639,8 @@ private void TestContextConversions() MostPopularProduct = product }; AssertExtensions.ExpectException(() => Context.ToDocument(product), typeof(InvalidOperationException)); - AssertExtensions.ExpectException(() => Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV1 }), typeof(InvalidOperationException)); - AssertExtensions.ExpectException(() => Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV2 }), typeof(InvalidOperationException)); + AssertExtensions.ExpectException(() => Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV1 }), typeof(InvalidOperationException)); + AssertExtensions.ExpectException(() => Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV2 }), typeof(InvalidOperationException)); // Remove circular dependence product.CompanyInfo.MostPopularProduct = new Product @@ -652,29 +652,29 @@ private void TestContextConversions() TagSet = new HashSet { "Test" }, }; - var docV1 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV1 }); - var docV2 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV2 }); + var docV1 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV1 }); + var docV2 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV2 }); VerifyConversions(docV1, docV2); } // Introduce circular reference in a Document and try to deserialize { // Normal serialization - var docV1 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV1 }); - var docV2 = Context.ToDocument(product, new DynamoDBOperationConfig { Conversion = conversionV2 }); + var docV1 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV1 }); + var docV2 = Context.ToDocument(product, new ToDocumentConfig { Conversion = conversionV2 }); VerifyConversions(docV1, docV2); // Add circular references docV1["CompanyInfo"].AsDocument()["MostPopularProduct"] = docV1; docV2["CompanyInfo"].AsDocument()["MostPopularProduct"] = docV2; - AssertExtensions.ExpectException(() => Context.FromDocument(docV1, new DynamoDBOperationConfig { Conversion = conversionV1 })); - AssertExtensions.ExpectException(() => Context.FromDocument(docV2, new DynamoDBOperationConfig { Conversion = conversionV2 })); + AssertExtensions.ExpectException(() => Context.FromDocument(docV1, new FromDocumentConfig { Conversion = conversionV1 })); + AssertExtensions.ExpectException(() => Context.FromDocument(docV2, new FromDocumentConfig { Conversion = conversionV2 })); // Remove circular references docV1["CompanyInfo"].AsDocument()["MostPopularProduct"] = null; docV2["CompanyInfo"].AsDocument()["MostPopularProduct"] = docV1; - var prod1 = Context.FromDocument(docV1, new DynamoDBOperationConfig { Conversion = conversionV1 }); - var prod2 = Context.FromDocument(docV2, new DynamoDBOperationConfig { Conversion = conversionV2 }); + var prod1 = Context.FromDocument(docV1, new FromDocumentConfig { Conversion = conversionV1 }); + var prod2 = Context.FromDocument(docV2, new FromDocumentConfig { Conversion = conversionV2 }); } } @@ -1099,7 +1099,7 @@ private void TestHashObjects() Assert.AreEqual(retrieved.Name, "Alan"); retrieved = Context.Load(employee); Assert.AreEqual(retrieved.Name, "Chuck"); - retrieved = Context.Load(employee2, new DynamoDBOperationConfig { ConsistentRead = true }); + retrieved = Context.Load(employee2, new LoadConfig { ConsistentRead = true }); Assert.AreEqual(retrieved.Name, "Diane"); Assert.AreEqual(retrieved.Age, 24); diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs index 49a66b677a20..583ca879b8f9 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/DataModelOperationSpecificConfigTests.cs @@ -289,6 +289,123 @@ public void FromScanConfig_OverridesTableName() mockClient.VerifyAll(); } + [TestMethod] + 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); + } + + [TestMethod] + public void DeleteConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.DeleteItem(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new DeleteItemResponse()) + .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 deleteConfig = new DeleteConfig() { TableNamePrefix = "OperationPrefix-" }; + + context.Delete("123", "Name", deleteConfig); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void SaveConfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.UpdateItem(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new UpdateItemResponse()) + .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 saveConfig = new SaveConfig() { TableNamePrefix = "OperationPrefix-" }; + + context.Save(new DataModel { Id = "123", Name = "Name"}, saveConfig); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + public void Loadonfig_OverridesTableName() + { + var mockClient = new Mock(); + mockClient.Setup(client => client.GetItem(It.Is(request => request.TableName == "OperationPrefix-TableName"))) + .Returns(new GetItemResponse()) + .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 loadConfig = new LoadConfig() { TableNamePrefix = "OperationPrefix-" }; + + context.Load("123", "Name", loadConfig); + + // We expect the setup with the correct prefix to have been called, otherwise an exception would have been thrown + mockClient.VerifyAll(); + } + + [TestMethod] + 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); + } + + [TestMethod] + 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); + } + + [TestMethod] + 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); + } + [DynamoDBTable("TableName")] private class DataModel { From 5142b520a04ac75ad196b5173315bcd98924e56c Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Wed, 7 Aug 2024 15:12:16 -0400 Subject: [PATCH 5/8] chore: Manually fix comments after rebase --- .../Custom/DataModel/_async/IDynamoDBContext.Async.cs | 2 -- .../Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) 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 030ee738d2fc..7f10ebfa10c7 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs @@ -192,8 +192,6 @@ partial interface IDynamoDBContext /// Loads an object from DynamoDB for the given hash-and-range primary key. /// /// - /// This invokes DynamoDB's GetItem operation, which returns an item with the given primary key. - /// The type must be marked up with and at least /// one public field/property with . /// 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 dc4d0e509146..504f5a2ee868 100644 --- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs +++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs @@ -187,12 +187,7 @@ partial interface IDynamoDBContext /// A partially-specified instance, where the /// hash/range properties are equal to the key of the item you /// want to load. - /// - /// The type must be marked up with and at least - /// one public field/property with . - /// - /// Type to populate. - /// Key object defining the the target item. + /// /// /// Object of type T, populated with properties of item loaded from DynamoDB. /// From dd833bb948d822d88a916337d199b5f72af85e55 Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Wed, 7 Aug 2024 15:19:24 -0400 Subject: [PATCH 6/8] chore: Move misplaced files --- .../Services/DynamoDBv2/Custom/{ => DataModel}/FromQueryConfig.cs | 0 .../Services/DynamoDBv2/Custom/{ => DataModel}/FromScanConfig.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename sdk/src/Services/DynamoDBv2/Custom/{ => DataModel}/FromQueryConfig.cs (100%) rename sdk/src/Services/DynamoDBv2/Custom/{ => DataModel}/FromScanConfig.cs (100%) diff --git a/sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/FromQueryConfig.cs similarity index 100% rename from sdk/src/Services/DynamoDBv2/Custom/FromQueryConfig.cs rename to sdk/src/Services/DynamoDBv2/Custom/DataModel/FromQueryConfig.cs diff --git a/sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/FromScanConfig.cs similarity index 100% rename from sdk/src/Services/DynamoDBv2/Custom/FromScanConfig.cs rename to sdk/src/Services/DynamoDBv2/Custom/DataModel/FromScanConfig.cs From 99193a0e3bc88f62e18b84786a61f6c8580098fe Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Thu, 8 Aug 2024 10:46:34 -0400 Subject: [PATCH 7/8] test: Avoid ambiguous call between obsolete and new DynamoDB ScanAsync methods --- .../IntegrationTests/DynamoDB/DataModelTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DataModelTests.cs b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DataModelTests.cs index 69b343c473e6..f4e65d4fba98 100644 --- a/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DataModelTests.cs +++ b/sdk/test/NetStandard/IntegrationTests/IntegrationTests/DynamoDB/DataModelTests.cs @@ -68,10 +68,10 @@ private async Task TestUnsupportedTypes() Assert.Equal("Type Amazon.DNXCore.IntegrationTests.DynamoDB.DynamoDBTests+EmptyType is unsupported, it has no supported members", exception.Message); // Verify that objects that are invalid result in exceptions - exception = await Assert.ThrowsAsync(() => SharedTestFixture.Context.ScanAsync(new List(), null).GetNextSetAsync()); + exception = await Assert.ThrowsAsync(() => SharedTestFixture.Context.ScanAsync(new List()).GetNextSetAsync()); Assert.Equal("Type System.TimeSpan is unsupported, it cannot be instantiated", exception.Message); - exception = await Assert.ThrowsAsync(() => SharedTestFixture.Context.ScanAsync(new List(), null).GetNextSetAsync()); + exception = await Assert.ThrowsAsync(() => SharedTestFixture.Context.ScanAsync(new List()).GetNextSetAsync()); Assert.Equal("Type Amazon.DNXCore.IntegrationTests.DynamoDB.DynamoDBTests+EmptyType is unsupported, it has no supported members", exception.Message); } From 181e595a67a0f29d98e40118cecb02f9cf516468 Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Thu, 8 Aug 2024 15:36:06 -0400 Subject: [PATCH 8/8] Add back change to a moved method that was lost when rebasing --- sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockingTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockingTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockingTests.cs index 7fb590c82f08..9beb4b085e9e 100644 --- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockingTests.cs +++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockingTests.cs @@ -27,8 +27,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 );