将 C# 数据结构存储到 SQL 数据库中
本文关键字:SQL 数据库 存储 数据结构 | 更新日期: 2023-09-27 17:47:21
我是 ASP.NET 和SQL服务器世界的新手,所以请原谅我的无知...
如果我在 C# 中有一个数据结构(例如,让我们说,一个存储一些字符串的向量),是否可以像在 SQL 表中一样存储向量的内容?我想这样做,以便尽快将数据转换回矢量形式,而无需逐个元素构建它。几乎就像将二进制数据写入文件,然后读取它并将其复制到 C 中的分配结构中一样。
我在SQL Server 2008上创建了一个表,其中的字段定义为VARBINARY(MAX)。我想我会从这个开始。
有人可以给我看一个例子,说明我将如何在该字段中存储和检索 10 个字符串的向量吗?这甚至可能吗(我想不出为什么不)?
谢谢!
首先,有一个明显的途径,即简单地创建一个关系结构并将对象映射到数据库中的字段。
其次,如果您有一个可序列化的对象,则可以将其存储在 SQL 服务器中。 我有时会这样做,并使用 SQL Server 中的文本数据类型来存储 XML。
意见:我更喜欢将序列化对象存储为 XML 而不是二进制数据。 为什么? 因为您实际上可以读取其中的内容(用于调试),而在 SQL Server 中,您可以使用 XQuery 从序列化对象中选择数据。 根据我的经验,与拥有更易于调试且可以以伪关系方式使用的数据相比,使用二进制数据的性能提升是不值得的。 看看SQL Server的XQuery功能。 即使您不打算立即使用它,也没有理由将自己置于角落。
您可以查看一些使用 NetDataContractSerializer 的示例。
我相信你所说的向量是 List<>在 C# 中。 看看System.Collections.Generic。 可以使用 NetDataContractSerializer 序列化包含 3 个字符串的列表,如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
namespace SerializeThingy
{
class Program
{
static void Main(string[] args)
{
List<string> myList = new List<string>();
myList.Add("One");
myList.Add("Two");
myList.Add("Three");
NetDataContractSerializer serializer = new NetDataContractSerializer();
MemoryStream stream = new MemoryStream();
serializer.Serialize(stream, myList);
stream.Position = 0;
Console.WriteLine(ASCIIEncoding.ASCII.GetString(stream.ToArray()));
List<string> myList2 = (List<string>)serializer.Deserialize(stream);
Console.WriteLine(myList2[0]);
Console.ReadKey();
}
}
}
此示例只是序列化一个列表,将序列化输出到控制台,然后证明它在另一面正确冻结。 我想你可以看到,从这里你可以将内存流转储到一个字符串中并将其写入数据库,或者使用内存流以外的其他流类型来做到这一点。
请记住参考 System.Runtime.Serialization 以访问 NetDataContractSerializer。
[Serializable]
public struct Vector3
{
public double x, y, z;
}
class Program
{
static void Main(string[] args)
{
Vector3 vector = new Vector3();
vector.x = 1;
vector.y = 2;
vector.z = 3;
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, vector);
string str = System.Convert.ToBase64String(memoryStream.ToArray());
//Store str into the database
}
}
假设对象标有[Serializable]
或实现ISerializable
,BinaryFormatter
类提供了一种简单的方法来做到这一点。
如果没有,您正在查看(非平凡的)自定义代码。
如果你要这样做(我想这在技术上是可行的),你也可以使用平面文件:使用关系数据库已经没有意义了。
这是泛型列表的另一种更通用的方法。 注意,存储在列表中的实际类型也必须是可序列化的
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Data.SqlClient;
using System.Runtime.Serialization;
public byte[] SerializeList<T>(List<T> list)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, list);
ms.Position = 0;
byte[] serializedList = new byte[ms.Length];
ms.Read(serializedList, 0, (int)ms.Length);
ms.Close();
return serializedList;
}
public List<T> DeserializeList<T>(byte[] data)
{
try
{
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
BinaryFormatter bf = new BinaryFormatter();
List<T> list = bf.Deserialize(ms) as List<T>;
return list;
}
catch (SerializationException ex)
{
// Handle deserialization problems here.
Debug.WriteLine(ex.ToString());
return null;
}
}
然后在客户端代码中:
List<string> stringList = new List<string>() { "January", "February", "March" };
byte[] data = SerializeList<string>(stringList);
存储/检索此字节数组的一种基本方法是使用简单的 SQLClient 对象:
SqlParameter param = new SqlParameter("columnName", SqlDbType.Binary, data.Length);
param.Value = data;
etc...
有理由保持灵活性。不应允许数据库结构的规则或准则阻碍创造力。给定这里的第一个线程,我也可以看到一种用于存储序列化列和约束列的混合方法。许多应用程序可以通过保持对可能性的开放态度来大大改进。
无论如何,我很欣赏新手对此事的看法。让我们都保持新鲜感。
我在关系数据库方面比 c# 有更多的经验,但二进制序列化是一种可接受的方法,因为它允许将整个对象的状态保存到数据库中。 XML 序列化几乎相同,但不允许泛型类型。