我可以在 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时间保存当前日期的问题
在SQL Server中保存一年中所选月份并在WPF中显示的数据结构[关闭]