Сериализация и управление версиями - PullRequest
5 голосов
/ 06 июля 2010

Мне нужно сериализовать некоторые данные в строку.Затем строка сохраняется в БД в специальном столбце SerializeData.

Я создал специальные классы для сериализации.

[Serializable]
public class SerializableContingentOrder
{
    public Guid SomeGuidData { get; set; }
    public decimal SomeDecimalData { get; set; }
    public MyEnumerationType1 EnumData1 { get; set; }
}

Сериализация:

protected override string Serialize()
{
    SerializableContingentOrder sco = new SerializableContingentOrder(this);

    MemoryStream ms = new MemoryStream();
    SoapFormatter sf = new SoapFormatter();
    sf.Serialize(ms, sco);
    string data = Convert.ToBase64String(ms.ToArray());
    ms.Close();
    return data;
}

Десериализация:

protected override bool Deserialize(string data)
{
    MemoryStream ms = new MemoryStream(Convert.FromBase64String(data).ToArray());
    SoapFormatter sf = new SoapFormatter();

    SerializableContingentOrder sco = sf.Deserialize(ms) as SerializableContingentOrder;
    ms.Close();
    return true;
}

Теперь яхочу иметь поддержку версий.Что произойдет, если я изменю SerializableContingentOrder класс.Я хочу иметь возможность добавлять новые поля в будущем.

Нужно ли переходить на сериализацию DataContract?Пожалуйста, дайте мне короткий фрагмент?

Ответы [ 4 ]

10 голосов
/ 06 июля 2010

I настоятельно выступают против хранения BinaryFormatter или SoapFormatter данных в базе данных; это:

  • хрупкий
  • не поддерживает версию
  • не зависит от платформы

BinaryFormatter подходит для передачи данных между сборками .NET (одним нажатием), но я бы порекомендовал более предсказуемый сериализатор. DataContractSerializer является опцией (как JSON или XmlSerializer), но я не будет использовать NetDataContractSerializer по тем же причинам, что и выше. У меня будет искушение использовать protobuf-net, поскольку это эффективный двоичный файл в известном эффективном формате, независимый от платформы и устойчивый к версии!

Например:

[DataContract]
public class SerializableContingentOrder
{
    [DataMember(Order=1)] public Guid SomeGuidData { get; set; }
    [DataMember(Order=2)] public decimal SomeDecimalData { get; set; }
    [DataMember(Order=3)] public MyEnumerationType1 EnumData1 { get; set; }
}

Сериализация:

protected override string Serialize()
{
    SerializableContingentOrder sco = new SerializableContingentOrder(this);   
    using(MemoryStream ms = new MemoryStream()) {
        Serializer.Serialize(ms, sco);
        return Convert.ToBase64String(ms.ToArray());
    }
}

Десериализация:

protected override bool Deserialize(string data)
{
    using(MemoryStream ms = new MemoryStream(Convert.FromBase64String(data)) {
        SerializableContingentOrder sco =
               Serializer.Deserialize<SerializableContingentOrder>(ms)
    }
    return true;
}
6 голосов
/ 06 июля 2010

У вас есть два варианта, если вы хотите поддерживать управление версиями.Используйте DataContracts или используйте сериализацию с допустимой версией.Оба действительны.

DataContacts обрабатывают добавление и удаление полей автоматически.См. Контроль версий данных и Рекомендации: Управление версиями данных для получения дополнительной информации.

Пример DataContact

[DataContract]
public class ContingentOrder
{
    [DataMember(Order=1)]
    public Guid TriggerDealAssetID;

    [DataMember(Order=2)]
    public decimal TriggerPrice;

    [DataMember(Order=3)]
    public TriggerPriceTypes TriggerPriceType;

    [DataMember(Order=4)]
    public PriceTriggeringConditions PriceTriggeringCondition;

}

Пример толерантности к версии

// Version 1
[Serializable]
public class SerializableContingentOrder
{
    public Guid TriggerDealAssetID;
    public decimal TriggerPrice;
    public TriggerPriceTypes TriggerPriceType;
    // Omitted PriceTriggeringCondition as an example
}

// Version 2 
[Serializable]
public class SerializableContingentOrder
{
    public Guid TriggerDealAssetID;
    public decimal TriggerPrice;
    public TriggerPriceTypes TriggerPriceType;

    [OptionalField(VersionAdded = 2)]
    public PriceTriggeringConditions PriceTriggeringCondition;

    [OnDeserializing]
    void SetCountryRegionDefault (StreamingContext sc)
    {
        PriceTriggeringCondition = /* DEFAULT VALUE */;
    }

}

Дополнительная информация по Версия TolerantСериализация .Особенно обратите внимание на лучшие практики внизу страницы.

Обратите внимание, что DataContracts были введены в .NET 3.5, поэтому у вас может не быть такой опции, если вам нужно ориентироваться на .NET 2.0.

HTH,

3 голосов
/ 06 июля 2010

Начиная с .NET 2.0 у вас есть поддержка сериализации с версионной версией, если вы используете BinaryFormatter.SoapFormatter также поддерживает некоторые поддерживаемые версиями функции, но не все, поддерживаемые BinaryFormatter, более конкретно, допуск на посторонние данные не поддерживается.

Для получения дополнительной информации вы должны проверить:

Версия Допустимая сериализация

1 голос
/ 06 июля 2010

Самый простой способ - украсить новые поля с помощью OptionalFieldAttribute.Это не идеально, но это может быть в вашем случае.

...