如何将C#类直接序列化到SQL Server中?

23

有人能建议一下将数据(实际上是一个类)序列化到数据库的最佳方法吗?

我正在使用 SQL Server 2008,但我认为在存储到数据库之前需要将类序列化为字符串或其他数据类型?

我认为这个字段需要是文本或二进制??

SQL Server 2008(或 .NET 3.5)是否支持直接将序列化后的数据存储到数据库中?

非常感谢任何帮助

6个回答

37

您可以将该类xml序列化成一个xml字段。我们经常在ETL中用于异常日志记录。

使用XmlSerializer,您可能需要在某个地方编写一个辅助方法,将该类序列化为字符串...

public static string SerializeToXml<T>(T value)
{
    StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    serializer.Serialize(writer, value);
    return writer.ToString();
}

那么就像处理其他字符串一样,将该字符串放入数据库中即可。

为什么我没想到用泛型来解决这个问题呢?扇自己一个耳光 - tom.dietrich
2
@tom - 这里不需要使用泛型。你同样可以使用“object value”,然后在构造序列化器时调用“value.GetType()”。 - Greg Beech
但是如何确保我的序列化XML文本长度不超过SQL Server中可用字段长度呢? - Laserson
2
我喜欢这种方法,但是我在反序列化XML时遇到了困难。我想从XML中确定类型并将其反序列化回原始对象... - Schenz
添加了一个方法,将对字符串进行反序列化。 - R. Schreurs

20

在数据库中存储数据的最佳方法是按列 (按属性) 存储,这样可以进行查询和索引。使用ORM工具可以帮助实现。

不过,还可以将类序列化为CLOB/BLOB (varchar(max)/varbinary(max) 等)。

如果您需要这样做,请避免使用任何特定于实现或版本不兼容的东西; 特别是不要使用BinaryFormatter。基于协议的任何内容都应该能够工作;比如XmlSerializerDataContractSerializer等。或者对于快速二进制,也可以考虑使用 protobuf-net。

但我强调,按列存储会更好。


1
马克 - 为什么你建议避免使用BinaryFormatter?它的大小更小...另外,基于Contract的方法如何提高保存在数据库中的数据? - Royi Namir
@RoyiNamir 这个在版本控制方面可能会有严重的问题,因为它包含了完整的类型名称(包括程序集)等,并且还与字段相关。而且它也不是最小的选择。通常我会建议使用protobuf-net,它通常占用更少的空间,并且避免了所有版本控制的问题 - 但这可能有些主观。 - Marc Gravell
我明白了,但是仍然不理解“由于包含完整的类型名称”是什么意思。如果我存储类型(例如:List<Person>()),有什么问题吗?你能简单地解释一下吗?谢谢。 - Royi Namir
5
因为实际上是"Some.Namespace.Person,Some.Assembly.dll,1.0.23.4",如果您进行重构可能会出现问题(我看到这个问题许多次伤害了很多人),它是.NET特定的(无法在其他平台加载),并且依赖于字段名称(最好希望没有人切换到自动实现属性,因为那样会破坏代码)。它有一种通过事件序列化过多数据的习惯,并导致情况发生,即(不经过大量麻烦)无法获取数据。而且,它既不特别小,也不特别快。 - Marc Gravell

3
没有泛型(更好的解决方法)
public static string SerializeToXml(object value)
{
  StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
  XmlSerializer serializer = new XmlSerializer(value.GetType());
  serializer.Serialize(writer, value);
  return writer.ToString();
}

1

我已将对象序列化为XML并成功地存入数据库。由于我们知道文本的最大长度,因此使用了varchar(max)数据类型,而不是使用TEXT或二进制格式。

这是一个OLTP Web应用程序,我们发现使用具有xml数据类型的列会导致一些显着的CPU使用率,因为每次插入都会验证xml。在我们的情况下,从未查询过xml,因此没有xml查询功能对我们来说也没问题。


1

有几个选项:

运行时序列化,可序列化的对象标记为Serializable属性,在这种情况下,IFormatter类执行所有序列化工作。可序列化的对象可以是ISerializable,但是您需要实现GetObjectData()方法。运行时序列化的问题在于读取xml数据的程序需要了解CLR类型。

Xml序列化:与运行时序列化不同,这种情况下您将获得良好的互操作性。XmlSerializer类型包含Serialize()和Deserialize()方法,因此任何对象都可以序列化为XML并保存到数据库中,当您检索它时,可以轻松地进行反序列化。

要从数据库中读取数据,可以使用SqlCommand类方法执行SQL查询,即ExecuteXmlReader()。ExecuteXmlReader()返回一个XmlReader实例,它将读取您的xml数据。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接