Document creation/update serialization fails when document object implements interface
See original GitHub issueDescribe the bug Document create/update operations fail when implemented in a method that passes an object implementing an interface.
To Reproduce I’ve implemented a method to handle the creation/updating of documents that implement a specific interface. The relevant snippet of code is as follows:
private async Task TryDocumentActionAsync<T>(DocumentAction action, string databaseId, string tableName, T row)
where T : ICosmosDbItem
{
...
Container container = this.client.GetContainer(databaseId, tableName);
switch (action)
{
case DocumentAction.Create:
await container.CreateItemAsync(row).ConfigureAwait(false);
break;
case DocumentAction.Upsert:
await container.UpsertItemAsync(row).ConfigureAwait(false);
break;
}
...
}
DocumentAction
is an enum I’ve created.
Expected behavior Depending on the code branch executed, I expect a document to be created or updated in my database.
Actual behavior
I receive the following exception (or similar) when executing either SDK method: Could not create an instance of type FraudHunters.Library.Models.IRiskDataRow. Type is an interface or abstract class and cannot be instantiated. Path 'id', line 1, position 6.
Environment summary SDK Version: v3.5.1 OS Version: Windows
Additional context I am currently able to work around this issue by explicitly changing the document type to the underlying implemented class:
doc = Convert.ChangeType(doc, concreteType);
Here’s the relevant portion of the stack trace:
| 0 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject","level":0,"line":0}
| 1 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject","level":1,"line":0}
| 2 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal","level":2,"line":0}
| 3 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize","level":3,"line":0}
| 4 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.JsonSerializer.DeserializeInternal","level":4,"line":0}
| 5 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.JsonSerializer.Deserialize","level":5,"line":0}
| 6 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosJsonDotNetSerializer.FromStream","level":6,"line":0}
| 7 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream","level":7,"line":0}
| 8 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory.ToObjectInternal","level":8,"line":0}
| 9 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory.<CreateItemResponseAsync>b__6_0","level":9,"line":0}
| 10 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory+<ProcessMessageAsync>d__16`1.MoveNext","level":10,"line":0}
| 11 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":11,"line":0}
| 12 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":12,"line":0}
| 13 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":13,"line":0}
| 14 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult","level":14,"line":0}
| 15 | {"assembly":"FraudHuntersLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","method":"FraudHunters.Library.FHDocumentClient+<TryDocumentActionAsync>d__14`1.MoveNext","level":15,"line":273,"fileName":"C:\\vsts-agent\\_work\\2\\s\\FraudHuntersLibrary\\Clients\\FHDocumentClient.cs"}
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
The scenario where an interface is being passed on
<T>
is working with the SDK v2.It’s a blocking point to work with a schemaless database and not being able to work with interfaces to insert documents. We could have a
<T>
being aList<ICompany>
where eachICompany
has a list of common properties & each concrete has dedicated properties to the current company.This is the stacktrace I had using the SDK v3 :
I created a repository with a sample usage using the SDK v2 & the SDK v3, it’s available here : https://github.com/YohanSciubukgian/CosmosDbConnector
Environment summary Microsoft.Azure.Cosmos : v3.6.0 Microsoft.Azure.DocumentDB.Core : v2.10.1 OS Version: Windows
I have created a dedicated issue : https://github.com/Azure/azure-cosmos-dotnet-v3/issues/1266