Проблема десериализации Appfabric DataCache на Get
У нас странная проблема с Appfabric DataCache. Иногда, может быть, 1 из 1000, мы получаем исключения из метода Get кеша cache.Get(key);
(public object Get(string key)
). Исключение составляет
Объект типа "System.Collections.Generic.List`1[MyNamespace.PersonName]" не может быть преобразован в тип "MyNamespace.StatusType".
Почему он пытается сделать это преобразование?? Тип StatusType не имеет ничего общего с типом PersonName и никак не связан с его графом объектов.
Это внутренняя часть DataCache, и, как уже упоминалось выше, он будет работать без проблем несколько дней, а иногда он просто начинает выдавать подобные исключения. Объекты (и графы объектов) достаточно просты. И это работает в 99% случаев.
Трассировки стека:
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck, Boolean doCheckConsistency)
at System.Runtime.Serialization.FormatterServices.SerializationSetValue(MemberInfo fi, Object target, Object value)
at System.Runtime.Serialization.FormatterServices.PopulateObjectMembers(Object obj, MemberInfo[] members, Object[] data)
at Castle.DynamicProxy.Serialization.ProxyObjectReference.DeserializeProxyState()
at Castle.DynamicProxy.Serialization.ProxyObjectReference..ctor(SerializationInfo info, StreamingContext context)
at ReadProxyObjectReferenceFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadPersonFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, String name, String ns)
at System.Runtime.Serialization.NetDataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)
at Microsoft.ApplicationServer.Caching.Utility.Deserialize(Byte[][] buffers, Boolean checkTypeToLoad)
at Microsoft.ApplicationServer.Caching.RoutingClient.SendMsgAndWait(RequestBody reqMsg)
at Microsoft.ApplicationServer.Caching.DataCache.SendReceive(RequestBody reqMsg)
at Microsoft.ApplicationServer.Caching.DataCache.InternalGet(String key, DataCacheItemVersion& version, String region)
at Microsoft.ApplicationServer.Caching.DataCache.Get(String key)
at MyNamespace.CacheManagement.AppFabricCacheProvider.Get(String key)
1 ответ
Отследил это в конце концов.
Эта проблема может возникнуть, если вы измените структуру вашего типа, когда кэшированная версия того же типа находится в кэше, а затем попытаетесь извлечь кэшированный экземпляр старого типа в ваш новый тип.
В среде с несколькими разработчиками, работающими над одними и теми же типами и использующими один и тот же глобальный кеш, вы обязательно столкнетесь с этим.
Никогда не встречается в производстве, где интерфейсы типов будут статическими.
пример
public class Foo // version 1.0
{
public string Woof {get;set;}
public FooBar Meow {get;set;}
}
// compile, run,
// add an instance of Foo to AppFabric Cache, cacheKey = X
// 5 mins later
public class Foo // version 1.1
{
public int Id {get;set;} // change interface of type
public string Woof {get;set;}
public FooBar Meow {get;set;}
}
// compile, run, get an instance of Foo from the cache, cacheKey = X
// exception, with strange information.