10

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

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

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

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

谢谢!

4

7 回答 7

24

首先,很明显的方法是简单地创建一个关系结构并将对象映射到数据库中的字段。

其次,如果您有一个可序列化的对象,您可以将它存储在 SQL Server 中。我有时会这样做,并使用 SQL Server 中的 Text 数据类型来存储 XML。

意见:我更喜欢将序列化对象存储为 XML 而不是二进制数据。为什么?因为您实际上可以读取其中的内容(用于调试),并且在 SQL Server 中您可以使用 XQuery 从序列化对象中选择数据。根据我的经验,与使用更易于调试且可以以伪关系方式使用的数据相比,使用二进制数据所带来的性能提升并不值得。看看SQL Server 的 XQuery 功能。即使您不打算立即使用它,也没有理由让自己陷入困境。

您可以查看一些使用NetDataContractSerializer的示例。

我相信你所说的向量是 C# 中的 List<> 。查看 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。

于 2008-10-20T00:15:13.893 回答
8
[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
    }
}
于 2008-10-20T00:19:16.943 回答
3

假设对象被标记[Serializable]或实现类提供ISerializableBinaryFormatter一种简单的方法来做到这一点。

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

于 2008-10-20T00:06:31.663 回答
2

如果您要这样做(我想这在技术上是可行的),您也可以使用平面文件:不再使用关系数据库。

于 2008-10-20T00:02:25.993 回答
2

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

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...
于 2008-10-20T00:40:37.897 回答
1

有理由保持灵活。不应允许数据库结构的规则或指导方针阻碍创造力。鉴于这里的第一个线程,我可以看到一种混合方法来存储序列化列和约束列。通过保持对可能性的开放态度,许多应用程序可以得到极大的改进。

无论如何,我很欣赏新手对此事的看法。让我们都保持新鲜..

于 2011-12-20T12:54:02.933 回答
0

与 c# 相比,我在关系数据库方面的经验更多,但二进制序列化是一种可接受的方式,因为它允许将整个对象的状态保存到数据库中。XML 序列化几乎相同,但不允许使用泛型类型。

于 2008-11-29T00:15:34.890 回答