Azure / azure-cosmos-table-dotnet

.NET SDK for Azure Cosmos Table API
14 stars 5 forks source link

Microsoft.Azure.Cosmos.Table.CloudTable fails to serialize Guid property named "ResourceId" #44

Open ananto-msft opened 4 years ago

ananto-msft commented 4 years ago

Describe the bug CloudTable fails to insert instance of TableEntity when there's proeprty named "ResourceId"

To Reproduce Our library is netstandard2.1 and it referencing the following Nuget package: Microsoft.Azure.Cosmos.Table version 1.0.6. We have class that inherits from Microsoft.Azure.Cosmos.Table.TableEntity. And we have defined Guid property named ResourceId.Example:

`public class CustomRecord : TableEntity { public CustomRecord(string partitionKey, string rowKey) : base(partitionKey, rowKey) { }

    public Guid ResourceId { get; set; }

}`

Trying to insert the record by using CloudTable.ExecuteAsync():

TableOperation tableOperation = TableOperation.InsertOrReplace(tableEntity); TableResult tableResult = await cloudTable.ExecuteAsync(tableOperation, cancellationToken).ConfigureAwait(false);

Expected behavior Properly insert new record to CosmosDB table.

Actual behavior Throws the following exception: "Microsoft.Azure.Cosmos.Table.StorageException: Cannot implicitly convert type 'Newtonsoft.Json.Linq.JObject' to 'string'. An explicit conversion exists (are you missing a cast?)\r\n ---> Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot implicitly convert type 'Newtonsoft.Json.Linq.JObject' to 'string'. An explicit conversion exists (are you missing a cast?)\r\n at CallSite.Target(Closure , CallSite , Object , Object )\r\n at Newtonsoft.Json.Serialization.JsonDynamicContract.TrySetMember(IDynamicMetaObjectProvider dynamicProvider, String name, Object value)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, String id)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)\r\n at Newtonsoft.Json.Se rialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)\r\n at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)\r\n at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)\r\n at Microsoft.Azure.Cosmos.Tables.SharedFiles.EntityTranslator.DeserializeObject[TObject](String value)\r\n at Microsoft.Azure.Cosmos.Tables.SharedFiles.EntityTranslator.GetDocumentFromEntityProperties(IDictionary2 properties, String partitionKey, String rowKey, Boolean removeSystemGeneratedProperties)\r\n at Microsoft.Azure.Cosmos.Table.Extensions.EntityHelpers.GetDocumentFromEntity(ITableEntity entity, OperationContext context, TableRequestOpt ions options)\r\n at Microsoft.Azure.Cosmos.Table.Extensions.TableExtensionOperationHelper.HandleUpsertAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context, CancellationToken cancellationToken)\r\n at Microsoft.Azure.Cosmos.Table.Extensions.TableExtensionOperationHelper.ExecuteOperationAsync[TResult](TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at Microsoft.Azure.Cosmos.Table.Extensions.TableExtensionOperationHelper.ExecuteOperationAsync[TResult](TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken)\r\n at Microsoft.Azure.Cosmos.Table.Extensions.TableExtensionRetryPolicy.ExecuteUnderRetryPolicy[TResult](Func1 executionMethod , CancellationToken cancellationToken, OperationContext operationContext, TableRequestOptions requestOptions)\r\n at Microsoft.AzureData.DataProcessing.Storage.StorageAccount.TableCosmosDbStorageClient.WriteAsync[TEntity](IStorageContext storageContext, IEnumerable`1 entities, CancellationToken cancellationToken) in D:\Repos\AdsHybrid\AdsHybrid\src\DataProcessing\Microsoft.AzureData.DataProcessing.Storage\CosmosDb\TableCosmosDbStorageClient.cs:line 132\r\nRequest Information\r\nRequestID:\r\nRequestCharge:0\r\nRequestDate:\r\nStatusMessage:Server encountered an internal error.Please try again after some time.\r\nErrorCode:\r\nErrorMessage:Cannot implicitly convert type 'Newtonsoft.Json.Linq.JObject' to 'string'. An explicit conversion exists (are you missing a cast?)\r\n"

Environment summary SDK Version: 3.1.200 OS Version: Windows 10

PaulCheng commented 4 years ago

While using CosmosDB Table store type, ResourceId is 1 of the reserved system properties. Other examples are Id, ETag, etc. I'll file a work item to improve exception message and sdk document. @Anton, can you work around this by using a different name?

ananto-msft commented 4 years ago

Hi @PaulCheng Yes, we did get it working with different name. Just wanted to file a bug so we can improve documentation and exception messaging. Also forgot to mention it appears it retries few times before erroring out. So perhaps fail fast would be also desirable for known reserved properties.

Thank you for your quick response. Looking forward the fix.