将 C# 数据结构存储到 SQL 数据库中

本文关键字:SQL 数据库 存储 数据结构 | 更新日期: 2023-09-27 17:47:21

我是 ASP.NET 和SQL服务器世界的新手,所以请原谅我的无知...

如果我在 C# 中有一个数据结构(例如,让我们说,一个存储一些字符串的向量),是否可以像在 SQL 表中一样存储向量的内容?我想这样做,以便尽快将数据转换回矢量形式,而无需逐个元素构建它。几乎就像将二进制数据写入文件,然后读取它并将其复制到 C 中的分配结构中一样。

我在SQL Server 2008上创建了一个表,其中的字段定义为VARBINARY(MAX)。我想我会从这个开始。

有人可以给我看一个例子,说明我将如何在该字段中存储和检索 10 个字符串的向量吗?这甚至可能吗(我想不出为什么不)?

谢谢!

将 C# 数据结构存储到 SQL 数据库中

首先,有一个明显的途径,即简单地创建一个关系结构并将对象映射到数据库中的字段。

其次,如果您有一个可序列化的对象,则可以将其存储在 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]或实现ISerializableBinaryFormatter类提供了一种简单的方法来做到这一点。

如果没有,您正在查看(非平凡的)自定义代码。

如果你要这样做(我想这在技术上是可行的),你也可以使用平面文件:使用关系数据库已经没有意义了。

这是泛型列表的另一种更通用的方法。 注意,存储在列表中的实际类型也必须是可序列化的

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 序列化几乎相同,但不允许泛型类型。