I’m using <PackageReference Include="Microsoft.Orleans.Sdk" Version="8.2.0" />
To generate a serializer for a pretty simple record:
namespace BaseNamespace.OldNameSpace;
[GenerateSerializer, Alias("MyRecord")]
public sealed record MyRecord
{
[Id(0)]
public string Name{ get; set; }
[Id(1)]
public int Age { get; set; }
}
I have a grain with the following constructor:
public sealed class MyRecordGrain([PersistentState(stateName: "MyRecordValue", MyRecordStorageKey")] IPersistentState<MyRecord> state) : IGrain, ICurrencyGrain
I manage to store the object and retrieve it through the constructor everytime I invoke the Grain. And in SQL Server it looks like this on the PayloadBinary column using select cast(PayloadBinary as varchar(MAX)), * from OrleansStorage
:
{
"$id": "1",
"$type": "BaseNamespace.OldNameSpace.MyRecord, MyProject.Common.Model",
"Name": "Anthony",
"Age ": 14,
},
The problem arises when I’m refactoring heavily class libraries and namespaces. If I change the namespace of MyRecord
from namespace BaseNamespace.OldNameSpace;
to namespace BaseNamespace.NewNameSpace;
and call the grain, the storage serialization will fail because the namespaces don’t match with this error:
Error from storage provider AdoNetGrainStorage.personCache during ReadStateAsync for grain personCache/PersonCacheKey
Exc level 0: Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON 'BaseNamespace.OldNameSpace.MyRecord, MyProject.Common.Model], System.Collections.Concurrent'. Path '$type', line 1, position 263.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolveTypeName(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, String qualifiedTypeName)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
If I change back the namespace to BaseNamespace.OldNameSpace
everything works fine. I know that I should add an alias
to the record classes so they support different versionings, but how could I avoid this namespace refactoring error? Why does the serialized data need to store about the assembly and the namespace if I’m already providing that information in the constructor of the grainIPersistentState<MyRecord>
?
Thanks!