【问题标题】:Can I save an 'Object' in a SQL Server database?我可以在 SQL Server 数据库中保存“对象”吗?
【发布时间】:2010-11-20 22:16:39
【问题描述】:

我想将一个对象(任何类型)保存到 SQL Server 2005 数据库的字段中。可以吗?我是否必须将对象转换为某种东西,例如字节数组,并在检索时将其转换回来?

【问题讨论】:

  • 您还可以序列化为 XML,这比二进制数据更容易在数据库中检查
  • 这不是一个很棒的数据库设计。您是否需要随时查询对象的属性?例如获取 object.Foo = 1 的所有对象。
  • 不,我不需要知道或查询存储的表的内容

标签: c# sql-server sql-server-2005 ado.net


【解决方案1】:

如果您愿意,可以在 SQL Server 中使用 VARBINARY(MAX) 字段类型。您可以在其中存储任何类型的对象,最大为 2 GB。

要访问它,您可以使用 ADO.NET - 类似这样:

object yourMysteryObject = (whatever you like it to be);

MemoryStream memStream = new MemoryStream();
StreamWriter sw = new StreamWriter(memStream);

sw.Write(yourMysteryObject);

SqlCommand sqlCmd = new SqlCommand("INSERT INTO TableName(VarBinaryColumn) VALUES (@VarBinary)", sqlConnection);

sqlCmd.Parameters.Add("@VarBinary", SqlDbType.VarBinary, Int32.MaxValue);

sqlCmd.Parameters["@VarBinary"].Value = memStream.GetBuffer();

sqlCmd.ExecuteNonQuery();

马克

【讨论】:

  • 但是如何将对象转换为 VARBINARY 类型?
  • 但这是从文件中读取的图像。如果我在运行时创建了一个类或对象怎么办。与文件无关。
  • 任何类型的对象都可以写入 MemoryStream 并分配给 SqlParameter 的值,然后将其写入数据库。
  • 如何将对象写入内存流?不处理硬盘? lz可以举个例子吗?
  • 嗯?如果您传递 sw.Write() 一个通用对象,它只会调用该对象的 ToString 方法!那不会序列化它!
【解决方案2】:

我会使用JSON 将对象转换为字符串,并将其存储在 VARCHAR 或 TEXT 字段中。数据不仅以人类可读的格式存储,而且还可以从不同的语言中读取,因为几乎每种主流语言都有可用的 JSON 解析器。

我发布的链接包含多个语言(包括 C#)的多个库的链接,我过去曾多次使用过 this one

【讨论】:

    【解决方案3】:

    正如其他人所说,序列化可能是这里的关键(假设您不想使用 ORM 将属性作为列存储在表中,这似乎更直接)。

    不过有一些注意事项;一个数据库是:

    • 长期存储
    • 与您的 .NET 代码无关

    因此,您确实想要使用任何特定于平台或特定于版本的序列化技术。你会经常看到人们提到BinaryFormatter 是为了持久化,但这属于上述两个陷阱。如果你改变了平台,或者即使你只是change some properties,你会被搞砸的。

    您需要一种独立于实现的方法;最简单的(也保留了人类可读的能力)是 xml 或 json,可能通过 XmlSerializer 或 Json.NET(存储在 [n]varchar(max) 中)。如果您不关心人类可读性,“协议缓冲区”(快速/二进制)会很好(存储在 varbinary(max) 中),并且是 available for most platforms(包括 C#/.NET/等)。

    【讨论】:

      【解决方案4】:

      如果您使用的是实体框架 (EF),以下是一个示例:

      using (DbContext db = new DbContext())
      {
          // The object that you want to serialize. In this case it is just an empty instance
          YourObject objectToSerialize = new YourObject();
          IFormatter formatter = new BinaryFormatter();
          using (MemoryStream stream = new MemoryStream())
          {
              formatter.Serialize(stream, objectToSerialize);
      
              // EF model. In one of its properties you store the serialized object
              YourModel modelObject = new YourModel();
      
              // In your model 'SerializedObject' should be of type byte[]. In the database it should be of type varbinary(MAX)
              modelObject.SerializedObject = stream.ToArray(); 
              db.YourModel.Add(modelObject);
              db.SaveChanges();
          }
      }
      

      这是反序列化对象的方法:

      // De-serialize
      IFormatter formatter = new BinaryFormatter();
      Stream stream = new MemoryStream(serializedObject);
      YourObject deserializedYourObject = (YourObject)formatter.Deserialize(stream);
      stream.Close();
      

      【讨论】:

      • 你如何将它转换回我们刚刚保存的对象......显然知道原始对象是什么。
      • @ppumpkin。我已经用如何反序列化对象的信息更新了我的答案。快乐编码:)
      • 被序列化的类必须标有 Serializable 属性。
      【解决方案5】:

      【讨论】:

      • 但我不想把它保存在硬盘上。我只是想把它放在一个数据库中。
      • BinaryFormatter 对于长期存储来说是一个非常糟糕的选择
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2017-03-30
      • 2017-12-04
      • 2011-10-09
      相关资源
      最近更新 更多