10

私は ASP.NET と SQL サーバーの世界に慣れていないので、私の無知を許してください...

C# にデータ構造がある場合 (たとえば、文字列を格納するベクトルなど)、ベクトルの内容をそのまま SQL テーブルに格納することはできますか? 要素ごとに構築する必要なく、そのデータをできるだけ早くベクトル形式に変換できるように、これを行いたいと考えています。バイナリ データをファイルに書き込み、それを読み取り、C で割り当てられた構造体にコピーするのとほとんど同じです。

フィールドが VARBINARY(MAX) として定義されている SQL Server 2008 でテーブルを作成しました。そこから始めようと思いました。

誰かが、たとえば10個の文字列のベクトルをそのフィールドに格納および取得する方法の例を教えてもらえますか? これは可能ですか(理由がわかりません)?

ありがとう!

4

7 に答える 7

24

まず、単純にリレーショナル構造を作成し、オブジェクトをデータベースのフィールドにマッピングするという明白な方法があります。

次に、シリアル化可能なオブジェクトがある場合は、それを SQL サーバーに格納できます。私は時々これを行い、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);

このバイト配列を保存/取得する基本的な方法の 1 つは、単純な 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 に答える