Search code examples
c#amazon-dynamodbaws-sdk-net

AWS SDK .NET DynamoDB ASYNC


I am trying to use AWS SDK for .NET Core.

  • Create a table to count views on videos.
  • Add a view count for a day.
  • Increment existing count for a day.
  • Query for video counts between two dates for a video.

.NET Core AWS SDK uses Async methods which are not documented in AWS. There is a feature request on their github page for this to happen.... but it is dated from last year. (https://github.com/aws/aws-sdk-net/issues/787)

CREATE THE TABLE

This works and creates a table on the AWS Console.

var ctRequest = new CreateTableRequest
{
    AttributeDefinitions = new List<AttributeDefinition>()
    {
        new AttributeDefinition
        {
            AttributeName = "ViewUid",
            AttributeType = ScalarAttributeType.S
        },
        new AttributeDefinition
        {
            AttributeName = "ViewDate",
            AttributeType = ScalarAttributeType.S
        }
    },
    KeySchema = new List<KeySchemaElement>
    {
        new KeySchemaElement
        {
            AttributeName = "ViewUid",
            KeyType = KeyType.HASH //Partition key
        },
        new KeySchemaElement
        {
            AttributeName = "ViewDate",
            KeyType = KeyType.RANGE
        }
    },
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = 5,
        WriteCapacityUnits = 6
    },
    TableName = _settings.AWSDynamoDBViewCountTable
};

var response = _client.CreateTableAsync(ctRequest).Result;

UPDATE AND ITEM WITH AUTO-INCREMENT A FIELD

This, sadly, is where i hit issues. The old docs are found here under the Atomic Counter section. (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html)

Invalid ConditionExpression: Syntax error; token: \"SET\", near: \"SET VC\"

var viewData = new Document();
viewData["ViewUid"] = videoUid; //Table entry UID
viewData["VideoId"] = videoId;  // Video ID
viewData["ViewDate"] = date;
viewData["ViewCount"] = 0;
//Document result = await _viewCountTable.PutItemAsync(viewData);

Expression expr = new Expression();
expr.ExpressionStatement = "SET #VC = #VC + :val";
expr.ExpressionAttributeValues[":val"] = 1;
expr.ExpressionAttributeNames["#VC"] = "ViewCount";
var updateConfig = new UpdateItemOperationConfig() { 
    ConditionalExpression = expr,
    ReturnValues = ReturnValues.UpdatedNewAttributes
};

var result = await _viewCountTable.UpdateItemAsync(viewData, updateConfig);
return result;

QUERY FOR DATE RANGE

Get one video's view count for a date range.

string queryTimeSpanStartString = dateFrom.ToString(AWSSDKUtils.ISO8601DateFormat);
string queryTimeSpanEndString = dateTo.ToString(AWSSDKUtils.ISO8601DateFormat);
var request = new QueryRequest
{
    TableName = _settings.AWSDynamoDBViewCountTable,
    KeyConditions = new Dictionary<string, Condition>()
    {
        {
            "VideoId",  new Condition()
            {
                ComparisonOperator = "EQ",
                AttributeValueList = new List<AttributeValue>()
                {
                    new AttributeValue { S = videoId }
                }
            }
        },
        {
            "ViewDate",
            new Condition
            {
                ComparisonOperator = "BETWEEN",
                AttributeValueList = new List<AttributeValue>()
                {
                    new AttributeValue { S = queryTimeSpanStartString },
                    new AttributeValue { S = queryTimeSpanEndString }
                }
            }
        }
    }
};

var response = await _client.QueryAsync(request);

Any help would be appreciated.


Solution

  • I was able to update the ViewCount with the following code:

    string tableName = "videos";

            var request = new UpdateItemRequest
            {
                Key = new Dictionary<string, AttributeValue>() { { "ViewUid", new AttributeValue { S = "replaceVideoIdhere" } } },
                ExpressionAttributeNames = new Dictionary<string, string>()
                {
                    {"#Q", "ViewCount"}
                },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
                {
                    {":incr", new AttributeValue {N = "1"}}
                },
                UpdateExpression = "SET #Q = #Q + :incr",
                TableName = tableName
            };
    
            var response = await _dynamoDbClient.UpdateItemAsync(request);
    

    I created a table called "videos" with a partition key named "ViewUid" as string. Let me know if this works for you.