ntext SQL字段中的不同字段序列化技术,同时保持向后兼容性

时间:2016-03-09 10:26:49

标签: c# sql serialization ntext

TL,DR:我们已经在SQL DB的某些表中序列化了一些数据。不幸的是,序列化技术浪费了很多标记字符的空间。我们找到了一种新的,更有效的方法:保持向后兼容性,采用以下逻辑是否安全? - >当序列化发生时,它总是使用新的,更有效的方式发生。当反序列化发生时,我们检查字符串是使用新的序列化格式还是旧的序列化格式 - >然后我们用适当的方法反序列化。这很健壮吗?这可以用于生产吗? Aren这种方法有任何微妙的问题吗?

问候。我正在开发一个与SQL数据库交互的应用程序。为了达到特定的业务需求,我们已经在类型为 ntext 的数据库表的特殊列中序列化了一些数据。基本上,在本专栏的每个单元格中,我们序列化了一个" Attributo"对象,所以 typeof(T)是Attributo []

" Attributo"定义如下:

public class Attributo
{
    public virtual String Nome { get; set; }
    public virtual String Valore { get; set; }
    public virtual String Tipologia { get; set; }
}

- 反序列化以读取实际值:

XMLUtilities.Deserialize<Attributo[]>(value));
  • 序列化以将值存储在列中(对于每一行......):

    XMLUtilities.Serialize(attributes.ToArray());

这是辅助类,它使用XmlSerializer对象:

public static class XMLUtilities
{
    public static T Deserialize<T>(String xmlString)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));

        using (TextReader reader = new StringReader(xmlString))
        {
            return (T) serializer.Deserialize(reader);
        }
    }

    public static String Serialize<T>(T xmlObject)
    {
        MemoryStream stream = new MemoryStream();

        XmlSerializer serializer = new XmlSerializer(typeof(T));

        XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
        xmlnsEmpty.Add("", "");

        serializer.Serialize(stream, xmlObject, xmlnsEmpty);

        stream.Seek(0, SeekOrigin.Begin);

        using (StreamReader reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    }
}

现在,这种技术的问题在于它为标记字符浪费了大量空间。这是一个存储在db:

上的示例字符串
<?xml version="1.0"?>
<ArrayOfAttributo>
  <Attributo>
    <Nome>Leakage_test_Time_prg1_p1</Nome>
    <Valore>4</Valore>
    <Tipologia>Single</Tipologia>
  </Attributo>
  <Attributo>
    <Nome>Leakage_air_Volume_p1</Nome>
    <Valore>14</Valore>
    <Tipologia>Single</Tipologia>
  </Attributo>
</ArrayOfAttributo>

因此,我们发现了一种更简洁的序列化这些Attributo []的方法,它产生了这种输出:

<ArrayOfA xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <A>
    <N>Leakage_test_Time_prg1_p1</N>
    <V>4</V>
    <T>Single</T>
  </A>
  <A>
    <N>Leakage_air_Volume_p1</N>
    <V>14</V>
    <T>Single</T>
  </A>
</ArrayOfA>

然后,保持向后兼容性,这是核心问题我们已经实现了以下逻辑:

  • 序列化期间:

我们总是以新的,更简洁的方式序列化

  • 反序列化期间:

我们检查字符串是否以:

开头
<?xml version="1.0"?>
是不是。如果是这种情况,这是一个旧条目,所以我们以旧方式反序列化它。否则,我们使用新格式反序列化。

我们通过装饰&#34; Attributo&#34;这样:

[DataContract(Name = "A", Namespace= "")]
public class Attributo
{
    [DataMember(Name = "N")]
    public virtual String Nome { get; set; }
    [DataMember(Name = "V")]
    public virtual String Valore { get; set; }
    [DataMember(Name = "T")]
    public virtual String Tipologia { get; set; }
}

并对我们的序列化/反序列化方法执行以下更改,现在,对于新的序列化技术,依赖于DataContractSerializer对象:

public static T Deserialize<T>(String xmlString)
{               
    //let's see if it's an old-style entry...
    if (xmlString.StartsWith("<?xml version=\"1.0\"?>\r\n<ArrayOfAttributo>"))
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));

            using (TextReader reader = new StringReader(xmlString))
            {
                return (T)serializer.Deserialize(reader);
            }
        }
        catch { }
    }

    //..then it must be a new-style one
    DataContractSerializer ser = new DataContractSerializer(typeof(T));

    using (Stream s = _streamFromString(xmlString))
    {
        return (T) ser.ReadObject(s);
    }
}

public static String Serialize<T>(T xmlObject)
{
    MemoryStream stream1 = new MemoryStream();
    DataContractSerializer ser = new DataContractSerializer(typeof(T));
    ser.WriteObject(stream1, xmlObject);
    stream1.Position = 0;
    StreamReader sr = new StreamReader(stream1);

    string xmlString = sr.ReadToEnd();

    return xmlString;    
}

private static Stream _streamFromString(string s)
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

一切似乎都在使用这种方法,但我们希望在继续进行之前评估所有可能的风险。这在生产中使用是否安全?

1 个答案:

答案 0 :(得分:1)

在对旧条目进行反序列化时要记住的另一件事是:

  1. 反序列化旧式
  2. 中的旧条目
  3. 序列化旧式
  4. 中的旧条目
  5. 保存 new-style-serialized-old-entry,删除旧式序列化旧条目。
  6. 你很高兴。