Обратите внимание, что использование здесь protobuf-net в основном имеет смысл только в том случае, если вы хотите перейти к постоянному поставщику состояний в какой-то момент.
Во-первых, поскольку вы используете in-memoryна данный момент (чтобы типы не сериализовались, AFAIK), некоторые примечания об изменении сеанса для использования любого типа поставщика на основе сериализации:
- типы должны быть сериализуемыпровайдер (звучит очевидно, но это имеет особое значение, если у вас есть круговые диаграммы и т. д.)
- , поскольку данные сериализуются, семантика отличается;вы получаете копию каждый раз, что означает, что любые изменения, сделанные вами во время запроса, будут потеряны - это нормально, если вы убедитесь, что вы снова явно сохраняете данные заново, и можете избежать некоторых проблем с потоками -обоюдоострые
- встроенные механизмы состояния обычно извлекают сеанс как одиночную операцию - что может быть проблемой, если (как вы упомянули) у вас есть большие объекты;не имеет ничего общего с protobuf-net, но однажды меня вызвали для исследования умирающего сервера, который оказался состоящим из нескольких МБ объектов в состоянии, убивающем систему, как каждый запрос (даже те, которые не используютэти данные) привели к транспортировке этого огромного объекта (в обоих направлениях) по сети
Во многих отношениях я на самом деле просто не фанат стандартной сессиимодель - и это еще до того, как я коснусь того, как это связано с protobuf-net!
protobuf-net, в конечном счете, является уровнем сериализации.Другая особенность стандартной реализации состояния сеанса состоит в том, что , поскольку изначально был написан с учетом BinaryFormatter
, предполагается, что объекты могут быть десериализованы без какого-либо дополнительного контекста.Однако protobuf-net (точно так же как XmlSerializer
, DataContractSerializer
и JavaScriptSerializer
) не привязан к какой-либо конкретной системе типов - он использует подход "вы говорите мне, какой тип вы хотите, чтобы я заполнял, я буду беспокоитьсяо данных ".На самом деле это невероятно хорошо , поскольку я видел, как веб-серверы убивали BinaryFormatter
при выпуске новых версий, потому что у кого-то была отвага , чтобы даже слегка прикоснуться к один из типов, который имел отношение к объекту, сохраненному в постоянном сеансе.BinaryFormatter
не нравится это; особенно , если вы (вздыхаете) переименовываете тип или ( shock ) создаете что-то из свойства field + в автоматически реализуемое свойство.Подсказка: это те проблемы, которые Google Protobuf разработал, чтобы избежать.
Однако!Это означает, что это не очень удобно для использования со стандартной моделью состояния сеанса.Я реализовал системы для кодирования имени типа в поток раньше (например, я написал транскодер enyim / memcached для protobuf-net), но ... это не красиво.ИМО, лучший способ сделать это - передать бремя , зная, что это за данные , на вызывающую сторону.Я имею в виду, действительно ... вызывающий должен знать, какой тип данных они ожидают в любом данном ключе, верно?
Один из способов сделать это - сохранить byte[]
.Практически любая реализация состояния может обрабатывать BLOB.Если это не сработает, просто используйте Convert.ToBase64String
/ Convert.FromBase64String
для хранения string
- любая реализация, не обрабатывающая string
, нуждается в стрельбе!Чтобы использовать с потоком, вы можете сделать что-то вроде (псевдокод здесь):
public static T GetFromState<T>(string key) {
byte[] blob = {standard state provider get by key}
using(var ms = new MemoryStream(blob)) {
return Serializer.Deserialize<T>(ms);
}
}
(и аналогично для добавления)
Обратите внимание, что protobuf-net отличается от BinaryFormatter
- у них разные ожидания того, что разумно, например, по умолчанию protobuf-net предполагает знать заранее как выглядят данные (т. е. public object Value {get;set;}
было бы больно), и не обрабатывает круговые графики (хотя существуют положения, поддерживающие оба этих сценария). Общее практическое правило: если вы можете сериализовать ваши данные с помощью чего-то вроде XmlSerializer
или DataContractSerializer
, они легко сериализуются с protobuf-net; Protobuf-net также поддерживает дополнительные сценарии, но не дает открытой гарантии сериализации каждой произвольной модели данных. Мышление с точки зрения DTO облегчит жизнь. В большинстве случаев это не проблема вообще , так как большинство людей имеют разумные данные. Некоторые люди не имеют разумные данные, и я просто хочу правильно рассчитать ожидание!
Лично, как я уже сказал - особенно , когда большие объекты могут быть вовлечены, я просто не фанат встроенного шаблона состояния сеанса. Вместо этого я мог бы предложить использовать отдельное хранилище данных для каждого ключа (то есть одну запись на пользователя на ключ, а не одну запись на пользователя) - возможно, только для более крупных объектов, может быть для всего. Это может быть SQL Server или что-то вроде redis / memcached. Очевидно, это немного болезненно, если вы используете сторонние элементы управления (веб-формы и т. Д.), Которые ожидают использовать состояние сеанса, но если вы используете состояние в своем коде вручную, это довольно просто реализовать. FWIW, BookSleeve в сочетании с Redis хорошо работает для таких вещей и обеспечивает достойный доступ к хранилищу на основе byte[]
. С byte[]
вы можете десериализовать объект, как показано выше.
В любом случае - я остановлюсь там, на случай, если зайду слишком далеко от темы; Не стесняйтесь отвечать на любые вопросы, но резюме:
- protobuf-net может остановить многие проблемы с версиями , которые могут возникнуть при
BinaryFormatter
- но это не обязательно прямой обмен 1: 1, так как protobuf-net не кодирует информацию «type» (которую ожидает встроенный механизм сеанса)
- его можно заставить работать, чаще всего с
byte[]
- но если вы храните большие объекты, у вас могут возникнуть другие проблемы (не связанные с protobuf-net), связанные с тем, как сессионное состояние хочет работать
- для больших объектов, в частности, я рекомендую использовать собственный механизм (т. Е. Не состояние сеанса); системы хранения значений ключей (redis, memcached, AppFabric cache) хорошо работают для этого