我是ASP.NET和SQL服务器的新手,所以请原谅我的无知......
如果我在C#中有一个数据结构(例如,让我们说,存储一些字符串的向量),是否可以像在SQL表中那样存储向量的内容?我想这样做,以便尽快将数据转换回矢量形式,而不必逐个元素地构造它。几乎就像将二进制数据写入文件然后读取它并将其复制到C中的已分配结构。
我在SQL Server 2008上创建了一个表,其中一个字段被定义为VARBINARY(MAX)。我以为我会从那开始。
有人可以向我展示一个例子,说明如何在该字段中存储和检索10个字符串的向量?这甚至是可能的(我想不出为什么不这样做)?
谢谢!
答案 0 :(得分:23)
首先,有一条简单的创建关系结构并将对象映射到数据库中的字段的明显路径。
其次,如果您有一个可序列化的对象,则可以将其存储在SQL Server中。我偶尔也这样做了,并使用SQL Server中的Text数据类型来存储XML。
意见:我更喜欢将序列化对象存储为XML而不是二进制数据。 为什么?因为您实际上可以读取其中的内容(用于调试),并且在SQL Server中,您可以使用XQuery从序列化对象中选择数据。根据我的经验,与使数据更容易调试并且可以以伪相关方式使用相比,使用二进制数据的性能提升将是不值得的。看看SQL Server's XQuery capabilities。即使你不打算立即使用它,也没有理由把自己放在角落里。
您可以使用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。
答案 1 :(得分: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
}
}
答案 2 :(得分:3)
假设对象标有[Serializable]
或实施ISerializable
,BinaryFormatter
类提供了一种简单的方法。
如果没有,您正在查看(非平凡的)自定义代码。
答案 3 :(得分:2)
如果您要这样做(我猜它在技术上可能可能),您也可以使用平面文件:再也不再使用关系数据库了。
答案 4 :(得分: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...
答案 5 :(得分:1)
有理由保持灵活性。不应允许数据库结构的规则或准则妨碍创造力。鉴于这里的第一个线程,我可以看到用于存储序列化和约束列的混合方法。许多应用程序可以通过让人们保持开放的可能性而得到极大改善。
无论如何,我对新事物的看法表示赞赏。让我们保持新鲜感......
答案 6 :(得分:0)
我对关系数据库比c#有更多的经验,但二进制序列化是一种可接受的方式,因为它允许将整个对象的状态保存到数据库中。 XML序列化几乎相同,但不允许使用泛型类型。