#c# #asp.net #nhibernate #session #state
#c# #asp.net #nhibernate #сеанс #состояние
Вопрос:
После обновления до NHibernate 3.1 и .Net 4 я вижу странное исключение в нашем веб-приложении. Сообщение об ошибке может быть знакомо многим:
Не удается сериализовать состояние сеанса. В режиме ‘StateServer’ и ‘SQLServer’, ASP.NET сериализует объекты состояния сеанса, и в результате несериализуемые объекты или объекты MarshalByRef не разрешены. То же ограничение применяется, если аналогичная сериализация выполняется пользовательским хранилищем состояния сеанса в «пользовательском» режиме.
Переключаясь в режим «InProc», все работает нормально. Но мы не можем использовать режим InProc в рабочей среде.
Теперь ошибка возникает только ОДИН раз. Затем удаляется до тех пор, пока приложение не будет повторно развернуто или перезапущено.
Ниже приведена полная трассировка стека в том виде, в каком она отображается в журнале. Пожалуйста, обратите внимание на следующие интересные моменты:
- PersistentGenericBag`1[DAL.DTO.Cargo] может указывать на то, что это связано с отложенной загрузкой
- Сериализатор пытается преобразовать его в Int32
- При исследовании содержимого сеанса я не могу найти абсолютно никаких объектов DTO или ссылок на какие-либо. Если я очищаю () сеанс, исключение исчезает, но наше приложение прерывается.
[Исключение InvalidCastException: не удается привести объект типа ‘NHibernate.Коллекция.Generic.PersistentGenericBag`1[DAL.DTO.Cargo]’ для ввода ‘System.IConvertible’.] Система.Преобразовать.ToInt32 (значение объекта, поставщик IFormatProvider) 21 System.Runtime.Сериализация.Форматеры.Двоичный файл._BinaryWriter.Значение записи (код InternalPrimitiveTypeE, значение объекта) 62 System.Runtime.Сериализация.Formatters.Binary._BinaryWriter.WriteMember(NameInfo memberNameInfo, NameInfo typeNameInfo, значение объекта) 76 System.Runtime.Сериализация.Форматеры.Двоичный файл.ObjectWriter.Класс WriteKnownValueClass(имя_имени_получателя, имя_имени_типа, объектные данные) 75 System.Runtime.Сериализация.Форматеры.Двоичный файл.ObjectWriter.WriteMembers (NameInfo memberNameInfo, NameInfo memberTypeNameInfo, Object MemberData, WriteObjectInfo ObjectInfo, NameInfo typeNameInfo, WriteObjectInfo memberObjectInfo) 198 System.Runtime.Сериализация.Форматеры.Двоичный файл.ObjectWriter.WriteMemberSetup (WriteObjectInfo ObjectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String MemberName, Type MemberType, Object MemberData, WriteObjectInfo memberObjectInfo) 139 System.Runtime.Сериализация.Форматеры.Двоичный файл.ObjectWriter.Запись (WriteObjectInfo ObjectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String[] MemberName, Type[] memberTypes, Object[] MemberData, WriteObjectInfo[] memberObjectInfos) 186 System.Runtime.Сериализация.Форматеры.Двоичный файл.ObjectWriter.Запись (WriteObjectInfo ObjectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) 480 Система.Время выполнения.Сериализация.Форматеры.Двоичный файл.ObjectWriter.Сериализовать (объектный граф, заголовочные[] заголовки, __BinaryWriter serWriter, логическая проверка fCheck) 444 System.Runtime.Сериализация.Форматеры.Двоичный файл.Двоичный форматировщик.Сериализовать (поток serializationStream, граф объектов, заголовки Header[], логический fCheck) 133 System.Web.Util.Повторная сериализация.WriteValueToStream (значение объекта, двоичный файл writer) 1708 <
[HttpException (0x80004005): не удается сериализовать состояние сеанса. В режиме ‘StateServer’ и ‘SQLServer’, ASP.NET сериализует объекты состояния сеанса, и в результате несериализуемые объекты или объекты MarshalByRef не разрешены. То же ограничение применяется, если аналогичная сериализация выполняется пользовательским хранилищем состояния сеанса в «пользовательском» режиме.] System.Web.Util.Повторная сериализация.WriteValueToStream (значение объекта, двоичный файл writer) 1793 System.Web.SessionState.SessionStateItemCollection.WriteValueToStreamWithAssert(значение объекта, двоичный файл writer) 34 System.Web.SessionState.SessionStateItemCollection.Сериализовать(BinaryWriter writer) 638 System.Web.SessionState.SessionStateUtility.Сериализовать (элемент SessionStateStoreData, поток Stream) 244 System.Web.SessionState.SessionStateUtility.SerializeStoreData (элемент SessionStateStoreData, размер начального потока Int32, байт [] и буфер, Int32 и длина, включено логическое сжатие) 67 System.Web.SessionState.OutOfProcSessionStateStore.SetAndReleaseItemExclusive (контекст HttpContext, идентификатор строки, элемент SessionStateStoreData, идентификатор блокировки объекта, логический новый элемент) 114 System.Web.SessionState.SessionStateModule.OnReleaseState(источник объекта, EventArgs EventArgs EventArgs) 807 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Выполнить() 148 System.Web.HttpApplication.ExecuteStep (шаг IExecutionStep, логическое значение и выполняется синхронно) 75
Ответ №1:
Это оказалось довольно неприятной проблемой. Действительно, были ссылки на объекты DTO, сохраненные в состоянии сеанса, но они были спрятаны достаточно глубоко, так что простая проверка содержимого сеанса вручную их не выявила.
На случай, если кто-либо еще столкнется с этой проблемой после обновления до NHib 3 и .Net 4; найдите воспроизводимый случай и внимательно изучите свой код или используйте инструменты анализа кода. Если не повезло, попробуйте идентифицировать весь код, который хранит данные в сеансе, и просто используйте грубую силу, пока не найдете некорректные данные. Удачи!