Хранение структуры данных C# в базе данных SQL
Я новичок в мире ASP.NET и SQL server, так что прошу простить мое невежество ...
Если у меня есть структура данных в C# (например, скажем, вектор, который хранит некоторые строки), можно ли хранить содержимое вектора, как в SQL-таблице? Я хочу сделать это так, чтобы он быстро преобразовал эти данные обратно в векторную форму как можно быстрее, не создавая его элемент за элементом. Почти как запись двоичных данных в файл, а затем чтение и копирование в него. выделенная структура в с.
Я создал таблицу на SQL Server 2008, для которой поле определено как VARBINARY (MAX). Я думал, что начну с этого.
Может ли кто-нибудь показать мне пример того, как я буду хранить и извлекать вектор, скажем, из 10 строк, в это поле и из него? Возможно ли это вообще (я не могу придумать, почему бы и нет)?
Спасибо!
7 ответов:
Во-первых, существует очевидный путь простого создания реляционной структуры и сопоставления объекта с полями в базе данных.
Во-вторых, если у вас есть сериализуемый объект, вы можете сохранить его в SQL server. Я делал это время от времени и использовал текстовый тип данных в SQL Server для хранения XML.мнение: я предпочитаю хранить сериализованные объекты в виде XML, а не двоичных данных. но почему? Потому что вы действительно можете прочитать, что там (для отладка), а в SQL Server можно использовать XQuery для выбора данных из сериализованного объекта. По моему опыту, выигрыш в производительности от использования двоичных данных не стоит того, чтобы сравнивать его с данными, которые легче отлаживать и которые можно использовать в режиме psuedo-relational. Взгляните на возможности XQuerySQL Server . Даже если вы не планируете использовать его сразу, нет причин ставить себя в угол.
Вы можете посмотреть на некоторые примеры, используя NetDataContractSerializer .
Я полагаю, что то, что вы называете вектором, является списком в C#. Загляните в систему.Коллекции.Родовой. Вы можете использовать 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(); } } }Этот пример просто сериализует список, выводит сериализацию на консоль, а затем доказывает, что она была правильно гидратирована на обратной стороне. Я думаю, вы можете увидеть, что отсюда вы можете либо сбросить поток памяти в строку и записать его в база данных, или использовать другой тип потока, чем поток памяти, чтобы сделать это.
Помните о системе отсчета.Во время выполнения.Сериализация для получения доступа к 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класс theBinaryFormatterдает простой способ сделать это.Если нет, то вы смотрите на (нетривиальный) пользовательский код.
Если вы собираетесь сделать это (и я думаю, что технически это возможно ), Вы можете также использовать плоский файл: нет смысла больше использовать реляционную базу данных.
Вот еще один более общий подход к общим спискам. Обратите внимание, что фактический тип, хранящийся в списке, также должен быть сериализуемым
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...
Есть причины быть гибким. Правила, или руководящие принципы, для структуры базы данных не должны препятствовать творчеству. Учитывая первый поток здесь, я вижу гибридный подход для хранения как сериализованных, так и ограничивающих столбцов. Многие приложения могут быть значительно улучшены, если держать свой ум открытым для возможностей.
В любом случае, я оценил точку зрения новичков на этот вопрос. Держит нас все свежее..
У меня больше опыта работы с реляционными базами данных, чем с#, но двоичная сериализация является приемлемым способом, так как она позволяет сохранять все состояние объекта в базе данных. XML-сериализация почти такая же, хотя универсальные типы не допускаются.
Comments