/// <summary>
 /// /// Specify the DeleteItem operation for the given primary key.
 /// </summary>
 /// <param name="primaryKey">Primary key of the item to delete.</param>
 /// <typeparam name="TRecord">The record type.</typeparam>
 public IDynamoTableDeleteItem <TRecord> DeleteItem <TRecord>(DynamoPrimaryKey <TRecord> primaryKey)
     where TRecord : class
 => new DynamoTableDeleteItem <TRecord>(this, new DeleteItemRequest {
     Key = new Dictionary <string, AttributeValue> {
         [primaryKey.PKName] = new AttributeValue(primaryKey.PKValue),
         [primaryKey.SKName] = new AttributeValue(primaryKey.SKValue)
     },
     TableName = TableName
 });
        //--- Methods ---

        /// <summary>
        /// Specify the GetItem operation for the given primary key.
        /// </summary>
        /// <param name="primaryKey">Primary key of the item to retrieve.</param>
        /// <param name="consistentRead">Boolean indicating if the read operation should be performed against the main partition (2x cost compared to eventual consistent read).</param>
        /// <typeparam name="TRecord">The record type.</typeparam>
        public IDynamoTableGetItem <TRecord> GetItem <TRecord>(DynamoPrimaryKey <TRecord> primaryKey, bool consistentRead = false)
            where TRecord : class
        => new DynamoTableGetItem <TRecord>(this, new GetItemRequest {
            ConsistentRead = consistentRead,
            Key            = new Dictionary <string, AttributeValue> {
                [primaryKey.PKName] = new AttributeValue(primaryKey.PKValue),
                [primaryKey.SKName] = new AttributeValue(primaryKey.SKValue)
            },
            TableName = TableName
        });
 /// <summary>
 /// Specify the PutItem operation for the given primary key and record. When successful, this operation creates a new row or replaces all attributes of the matching row.
 /// </summary>
 /// <param name="primaryKey">Primary key of the item to write.</param>
 /// <param name="record">The record to write</param>
 /// <typeparam name="TRecord">The record type.</typeparam>
 public IDynamoTablePutItem <TRecord> PutItem <TRecord>(DynamoPrimaryKey <TRecord> primaryKey, TRecord record)
     where TRecord : class
 => new DynamoTablePutItem <TRecord>(this, new PutItemRequest {
     Item      = SerializeItem(record, primaryKey),
     TableName = TableName
 });
        internal Dictionary <string, AttributeValue> SerializeItem <TRecord>(TRecord record, DynamoPrimaryKey <TRecord> primaryKey)
            where TRecord : class
        {
            var attributes = DynamoSerializer.Serialize(record, SerializerOptions)?.M;

            if (attributes is null)
            {
                throw new ArgumentException("cannot serialize null record", nameof(record));
            }

            // add type details
            attributes["_t"] = new AttributeValue(Options.GetShortTypeName(typeof(TRecord)));

            // add modified details
            attributes["_m"] = new AttributeValue {
                N = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(CultureInfo.InvariantCulture)
            };

            // add primary key details
            attributes[primaryKey.PKName] = new AttributeValue(primaryKey.PKValue);
            attributes[primaryKey.SKName] = new AttributeValue(primaryKey.SKValue);
            return(attributes);
        }