Хранение структуры данных C# в базе данных SQL

Я новичок в мире ASP.NET и SQL-сервера, поэтому прошу прощения за мое невежество...

Если у меня есть структура данных в C# (например, скажем, вектор, в котором хранятся некоторые строки), возможно ли сохранить содержимое вектора, как в таблице SQL? Я хочу сделать это так, чтобы быстро преобразовать эти данные обратно в векторную форму как можно быстрее, не создавая их поэлементно. Почти как запись двоичных данных в файл, а затем чтение и копирование в выделенную структуру на C.

Я создал таблицу на SQL Server 2008, для которой поле определено как VARBINARY(MAX). Я думал, что начну с этого.

Может ли кто-нибудь показать мне пример того, как я буду хранить и извлекать вектор, скажем, из 10 строк, в и из этого поля? Это вообще возможно (я не могу думать, почему нет)?

Спасибо!

7 ответов

Решение

Во-первых, существует очевидный путь простого создания реляционной структуры и сопоставления объекта с полями в базе данных.

Во-вторых, если у вас есть объект, который можно сериализировать, вы можете сохранить его на сервере SQL. Я делал это время от времени и использовал тип данных Text в 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 the 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 почти такая же, хотя универсальные типы не допускаются.

Другие вопросы по тегам