aws / aws-sdk-net

The official AWS SDK for .NET. For more information on the AWS SDK for .NET, see our web site:
http://aws.amazon.com/sdkfornet/
Apache License 2.0
2.05k stars 853 forks source link

DynamoDBContext DeleteAsync by key fails #2615

Open BryanCrotaz opened 1 year ago

BryanCrotaz commented 1 year ago

Describe the bug

The data table

   "WebsocketConnectionsTable": {
      "Type" : "AWS::DynamoDB::Table",
      "Properties" : {
          "AttributeDefinitions" : [ 
              {
                "AttributeName" : "conn",
                "AttributeType" : "S"
              }
          ],
          "BillingMode" : "PAY_PER_REQUEST",
          "ContributorInsightsSpecification" : {
            "Enabled" : false
          },
          "DeletionProtectionEnabled" : true,
          "GlobalSecondaryIndexes" : [
          ],
          "KeySchema" : [ 
            {
              "AttributeName" : "conn",
              "KeyType" : "HASH"
            }
          ],
          "TableClass" : "STANDARD",
          "TableName" : { 
            "Fn::Join" : [ 
              "-", 
              [ 
                "my-app",            
                { 
                  "Ref" : "StageNameParameter" 
                }, 
                "websocket-auth-table" 
              ] 
            ] 
          },
          "Tags" : [ ]
        }
    }
// the model
    [DynamoDBTable("websocket-auth-table")]
    public class WebsocketConnectionDB
    {
        public WebsocketConnectionDB()
        {
            ConnectionId = "";
            UserId = "";
        }

        [DynamoDBHashKey("conn")]
        public string ConnectionId { get; set; }

        [DynamoDBProperty("user")]
        public string UserId { get; set; }

        [DynamoDBProperty("connected")]
        public Int64 ConnectedAsNumber
        {
            get
            {
                return new DateTimeOffset(Connected).ToUnixTimeSeconds();
            }
            set
            {
                Connected = DateTimeOffset.FromUnixTimeSeconds(value).DateTime;
            }
        }

        [DynamoDBIgnore]
        public DateTime Connected { get; set; }
    }

The code - delete a row based on the hash


    public Task Delete(string id)
    {
               var operationConfig = new DynamoDBOperationConfig()
        {
            TableNamePrefix = this.tableNamePrefix
        };
        return dynamoContext.DeleteAsync<string>(id, operationConfig);
    }
fail    System.InvalidOperationException: Type System.String is unsupported, it cannot be instantiated   
at Amazon.DynamoDBv2.DataModel.StorageConfig..ctor(ITypeInfo targetTypeInfo)   
at Amazon.DynamoDBv2.DataModel.ItemStorageConfig..ctor(ITypeInfo targetTypeInfo)   
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.CreateStorageConfig(Type baseType, String actualTableName)   
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.GetConfig(Type type, DynamoDBFlatConfig flatConfig, Boolean conversionOnly)   
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.GetConfig[T](DynamoDBFlatConfig flatConfig, Boolean conversionOnly)   
at Amazon.DynamoDBv2.DataModel.DynamoDBContext.DeleteHelperAsync[T](Object hashKey, Object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)   
at Amazon.DynamoDBv2.DataModel.DynamoDBContext.DeleteAsync[T](Object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)   
at DynamoRepository`2.Delete(TId id)   
at DisplaySure.WebSockets.WebsocketEntryPoint.HandleDisconnect(APIGatewayProxyRequest request)   
at lambda_method1(Closure , Stream , ILambdaContext , Stream )   
at Amazon.Lambda.RuntimeSupport.Bootstrap.UserCodeLoader.Invoke(Stream lambdaData, ILambdaContext lambdaContext, Stream outStream) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/UserCodeLoader.cs:line 145   
at Amazon.Lambda.RuntimeSupport.HandlerWrapper.<>c__DisplayClass8_0.<GetHandlerWrapper>b__0(InvocationRequest invocation) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/HandlerWrapper.cs:line 55   
at Amazon.Lambda.RuntimeSupport.LambdaBootstrap.InvokeOnceAsync(CancellationToken cancellationToken) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/LambdaBootstrap.cs:line 176 | 2023-05-23T19:08:53.089Z e247f672-d020-428f-b0fb-adc3f4bdcea4 fail System.InvalidOperationException: Type System.String is unsupported, it cannot be instantiated at Amazon.DynamoDBv2.DataModel.StorageConfig..ctor(ITypeInfo targetTypeInfo) 
at Amazon.DynamoDBv2.DataModel.ItemStorageConfig..ctor(ITypeInfo targetTypeInfo) 
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.CreateStorageConfig(Type baseType, String actualTableName) 
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.GetConfig(Type type, DynamoDBFlatConfig flatConfig, Boolean conversionOnly) 
at Amazon.DynamoDBv2.DataModel.ItemStorageConfigCache.GetConfig[T](DynamoDBFlatConfig flatConfig, Boolean conversionOnly) 
at Amazon.DynamoDBv2.DataModel.DynamoDBContext.DeleteHelperAsync[T](Object hashKey, Object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
at Amazon.DynamoDBv2.DataModel.DynamoDBContext.DeleteAsync[T](Object hashKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken) at DynamoRepository`2.Delete(TId id) 
at DisplaySure.WebSockets.WebsocketEntryPoint.HandleDisconnect(APIGatewayProxyRequest request) 
at lambda_method1(Closure , Stream , ILambdaContext , Stream ) 
at Amazon.Lambda.RuntimeSupport.Bootstrap.UserCodeLoader.Invoke(Stream lambdaData, ILambdaContext lambdaContext, Stream outStream) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/UserCodeLoader.cs:line 145 
at Amazon.Lambda.RuntimeSupport.HandlerWrapper.<>c__DisplayClass8_0.<GetHandlerWrapper>b__0(InvocationRequest invocation) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/HandlerWrapper.cs:line 55 
at Amazon.Lambda.RuntimeSupport.LambdaBootstrap.InvokeOnceAsync(CancellationToken cancellationToken) in /src/Repo/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/LambdaBootstrap.cs:line 176

Expected Behavior

Expected the row with that hash Id to be deleted

Current Behavior

Exception, see above

Reproduction Steps

See above

Possible Solution

No response

Additional Information/Context

No response

AWS .NET SDK and/or Package version used

AWSSDK.DynamoDBv2 3.7.103.8

Targeted .NET Platform

.Net 6

Operating System and version

AWS Lambda

normj commented 1 year ago

@BryanCrotaz You need to change the

return dynamoContext.DeleteAsync<string>(id, operationConfig);

to

return dynamoContext.DeleteAsync<WebsocketConnectionDB>(id, operationConfig);

The generic parameter is used to identify the type and find the table's metadata.

BryanCrotaz commented 1 year ago

Interesting - that's not what the signature says.

DeleteAsync<TId>(TId id ...

That implies that the type is the type of the hash key. The other overload is

DeleteAsync<TModel>(TModel entity ...
BryanCrotaz commented 1 year ago

Your suggestion works but there's no way I would have guessed that from the signature and the docs.

BryanCrotaz commented 1 year ago

Docs I used: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetDynamoDBContext.html

normj commented 1 year ago

In all of the methods the generic parameter is the type of the entity you are working with. Otherwise the library has no context where you are deleting that string from.

I agree the nDoc for that parameter could be a lot more clear. I'm going to turn this into a feature request to update the generic parameter documentation in the code.