我可以在 SQL Server 数据库中保存“对象”吗?

Posted

技术标签:

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

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

【问题讨论】:

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

为此,您需要序列化您的对象。 你可以看这里的例子:

http://www.c-sharpcorner.com/UploadFile/bipinjoshi/serializingObjectsinCS11102005234746PM/serializingObjectsinCS.aspx

【讨论】:

但我不想把它保存在硬盘上。我只是想把它放在一个数据库中。 BinaryFormatter 对于长期存储来说是一个非常糟糕的选择

以上是关于我可以在 SQL Server 数据库中保存“对象”吗?的主要内容,如果未能解决你的问题,请参考以下文章

关于在SQL Server中使用UTC时间保存当前日期的问题

将 c# 对象存储在 sql server 数据库中

SQL Server游标

在SQL Server中保存一年中所选月份并在WPF中显示的数据结构[关闭]

解决sql server保存对象字符串转换成uniqueidentifier失败的问题

在 SQL Server Management Studio 中保存文件失败