简体   繁体   中英

Cannot query or scan DynamoDB in Unity

TLDR: Can't create an AsyncSearch object from QueryAsync or ScanAsync without running into a weird ArgumentNullException deep inside the AWS library.

I'm developing an online game in Unity and want to synchronize data with DynamoDB. When I only had a table with player data this worked very well. I would just use "DBContext.LoadAsync(id, callback);" and it works flawlessly. Saving with "SaveAsync" works just as well.

Now I introduced some more tables and I need to perform scans and queries. For testing purposes, I gave my Unity app all the rights it can possibly have (I used "dynamodb:*" and "Resource": ["*"] in IAM).

I tried basically all the possible versions of ScanAsync, QueryAsync and FromQueryAsync with different parameters but I just always get an error.

Simple example: I want to download all departments (of my university):

AsyncSearch<DepartmentData> search = AWSManager.Instance.DBContext.ScanAsync<DepartmentData>();

This call already fails, before I can do anything like "search.GetRemainingAsync(callback)". The same goes for for simple queries like:

AsyncSearch<POIVisit> query = AWSManager.Instance.DBContext.QueryAsync<POIVisit>(poiType);

The error is the following and is somewhere deep in the AWS library, so I can't really go in there, set some breakpoints and see what exactly is failing:

ArgumentNullException: Argument cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary`2[System.Type,Amazon.Runtime.IExceptionHandler].TryGetValue (System.Type key, IExceptionHandler& value) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:588)
Amazon.Runtime.Internal.ErrorHandler.ProcessException (IExecutionContext executionContext, System.Exception exception) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/ErrorHandler/ErrorHandler.cs:202)
Amazon.Runtime.Internal.ErrorHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/ErrorHandler/ErrorHandler.cs:78)
Amazon.Runtime.Internal.PipelineHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/PipelineHandler.cs:57)
Amazon.Runtime.Internal.CallbackHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/CallbackHandler.cs:45)
Amazon.Runtime.Internal.PipelineHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/PipelineHandler.cs:57)
Amazon.Runtime.Internal.Signer.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Signer.cs:38)
Amazon.Runtime.Internal.PipelineHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/PipelineHandler.cs:57)
Amazon.Runtime.Internal.CredentialsRetriever.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/CredentialsRetriever.cs:72)
Amazon.Runtime.Internal.PipelineHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/PipelineHandler.cs:57)
Amazon.Runtime.Internal.RetryHandler.InvokeSync (IExecutionContext executionContext) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Core/Amazon.Runtime/Pipeline/RetryHandler/RetryHandler.cs:74)

It gets even worse, if I want to query based on a secondary index. For that, I need to attach a DynamoDBOperationConfig after the conditions for hash and range key like so:

var queryConfig = new DynamoDBOperationConfig() { IndexName = "PlayerIndex" };
AsyncSearch<POIVisit> query = AWSManager.Instance.DBContext.QueryAsync<POIVisit>(poiType, QueryOperator.Equal, PlayerID, queryConfig);

Now, it somehow seems to think, the queryConfig is just another value for the range key (so it basically chooses the wrong overloaded version of QueryAsync). Or at least I think that's what happens, because I get a weird conversion error now:

InvalidCastException: Cannot cast from source type to destination type.
Amazon.DynamoDBv2.Converter`1[T].TryTo (System.Object value, Amazon.DynamoDBv2.DocumentModel.Primitive& p) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Services/DynamoDBv2/Custom/Conversion/DynamoDBEntryConversion.cs:630)
…
Amazon.DynamoDBv2.DataModel.DynamoDBContext.QueryAsync[POIVisit] (System.Object hashKeyValue, QueryOperator op, System.Object[] values) (at E:/JenkinsWorkspaces/v3-trebuchet-release/AWSDotNetPublic/sdk/src/Services/DynamoDBv2/Custom/DataModel/_unity/Context.Async.cs:550)
DBManager.RetrievePlayerVisits (System.String poiType, UnityEngine.Events.UnityAction`1 callback) (at Assets/Scripts/Managers/DBManager.cs:359)

My Unity version is 5.6.3f1. I tried AWSSDK.DynamoDBv2.3.3.4.18 and the older AWSSDK.DynamoDBv2.3.3.4.14 Unity packages containing the AWS SDK downloaded directly from Amazon.

If someone has a hint what I could be doing wrong, I'd be really grateful, thanks!

You need to build a request object before you create a query. I've never used Unity but it should be something like

var request = new QueryRequest();
request.TableName = "YourTable";   
request.KeyConditions = new Dictionary<string, Condition>()
{
    { 
        "YourId",  new Condition()
        { 
            ComparisonOperator = "EQ",
            AttributeValueList = new List<AttributeValue>()
            {
                new AttributeValue { S = YourId }
            }
        }
    }
};

client.QueryAsync(request,(result));

Specifically, it looks like you are not including your keycondition as part of the request, which is required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM