2008-10-19 25 views
9

Soy nuevo en el mundo de ASP.NET y el servidor SQL, así que por favor perdonen mi ignorancia ...# estructura de datos que almacena C en una base de datos SQL

Si tengo una estructura de datos en C# (por ejemplo, sólo vamos a por ejemplo, un vector que almacena algunas cadenas), ¿es posible almacenar el contenido del vector como está en la tabla SQL? Quiero hacer esto para que sea rápido convertir esos datos a formato vectorial lo más rápido posible sin tener que construirlo elemento por elemento. Casi como escribir datos binarios en un archivo y luego leerlo y copiarlo en una estructura asignada en C.

Creé una tabla en SQL Server 2008 para la cual un campo se define como VARBINARIO (MÁXIMO). Pensé que comenzaría con eso.

¿Podría alguien mostrarme un ejemplo de cómo me gustaría almacenar y recuperar un vector de, por ejemplo, 10 cadenas, dentro y desde ese campo? ¿Es esto posible (no puedo pensar por qué no)?

Gracias!

Respuesta

22

En primer lugar, existe la ruta obvia de simplemente crear una estructura relacional y asignar el objeto a los campos en la base de datos.

En segundo lugar, si tiene un objeto que es serializable, puede almacenarlo en el servidor SQL. Lo he hecho ocasionalmente, y he usado el tipo de datos de texto en SQL Server para almacenar el XML.

Opinión: Prefiero almacenar objetos serializados como XML en lugar de datos binarios. ¿Por qué? Como puede leer realmente lo que hay allí (para la depuración), y en SQL Server, puede usar XQuery para seleccionar datos del objeto serializado. Según mi experiencia, la ganancia de rendimiento del uso de datos binarios no valdrá la pena en comparación con tener datos que es más fácil de depurar y se puede usar de una manera psicorelacional. Eche un vistazo al SQL Server's XQuery capabilities. Incluso si no planeas usarlo de inmediato, no hay razón para ponerte en una esquina.

Puede consultar algunos ejemplos con el NetDataContractSerializer.

Creo que lo que usted llama un vector es una Lista <> en C#. Eche un vistazo en System.Collections.Generic. Se puede utilizar el NetDataContractSerializer para serializar una lista de 3 cuerdas como:

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(); 
     } 
    } 
} 

Este ejemplo simplemente serializa una lista, da salida a la serialización a la consola, y luego demuestra que fue hidratada correctamente en la otra cara. Creo que puede ver que desde aquí puede volcar la secuencia de la memoria en una cadena y escribirla en la base de datos, o usar otro tipo de flujo que una secuencia de memoria para hacerlo.

Recuerde hacer referencia a System.Runtime.Serialization para obtener acceso a NetDataContractSerializer.

+0

¡Respuesta impresionante, gracias! – cori

+0

@Jason Jackson Estoy de acuerdo contigo cuando dices ** "Prefiero almacenar objetos serializados como XML en lugar de datos binarios" **, pero ¿qué sucede si tengo que serializar las interfaces? – davioooh

+0

las interfaces no se pueden serializar, por lo que las propiedades implementadas se deben ignorar ... el método anterior es muy útil en algunos casos donde se requieren operaciones de mucho tiempo sobre la creación de estructuras de datos ... prefiero usar el serializador JSON de esa manera se ahorrará memoria ... –

2

Si va a hacer eso (y supongo que técnicamente es posible), también podría usar un archivo plano: ya no tiene sentido usar una base de datos relacional.

+1

¿Estás diciendo que si necesitas persistir en algo que no es un tipo de columna de base de datos integrada, deberías usar archivos planos? – MusiGenesis

+0

¿Por qué no utilizar una base de datos? Ciertamente tiene la ventaja de ser más escalable que un archivo plano. Y si usa un formato de serialización XML, también puede consultar los datos en SQL Server utilizando XQuery. –

+0

Si persiste un objeto complejo en una base de datos, cada campo en el objeto debe obtener su propia columna o tabla para que pueda buscar y consultar en ese campo. –

3

Suponiendo que los objetos están marcados con [Serializable] o implemente ISerializable, la clase BinaryFormatter ofrece una forma sencilla de hacerlo.

Si no, está buscando un código personalizado (no trivial).

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 
    } 
} 
+1

Por qué convertir en una cadena? Su columna es binaria. – MusiGenesis

+1

Si él viene de C, entonces un vector probablemente significa una lista: http://en.wikipedia.org/wiki/Std::vector –

2

Aquí hay otro enfoque más general para las listas genéricas. Tenga en cuenta, el tipo real almacenado en la lista también debe ser serializable

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; 
    } 

} 

Luego, en el código de cliente:

List<string> stringList = new List<string>() { "January", "February", "March" }; 

byte[] data = SerializeList<string>(stringList); 

Una forma básica de almacenamiento/recuperación de esta matriz de bytes podría ser el uso de objetos SQLClient simples :

SqlParameter param = new SqlParameter("columnName", SqlDbType.Binary, data.Length); 
param.Value = data; 

etc... 
0

tengo más experiencia con bases de datos relacionales que C#, pero serialización binaria es una forma aceptable para ir, ya que permite que el estado de todo el objeto a ser guardado int o la base de datos. La serialización XML es prácticamente la misma, aunque los tipos genéricos no están permitidos.

+0

pequeña corrección: se les permite tipos genéricos, si se utiliza la serialización DataContract o serialización NetDataContract, en vez que la serialización XML. –

1

Hay razones para ser flexible. No debe permitirse que las reglas o directrices para la estructura de la base de datos impidan la creatividad. Dado el primer hilo aquí, puedo ver un enfoque híbrido para almacenar columnas seriales y restrictivas también. Muchas aplicaciones se pueden mejorar enormemente al mantener la mente abierta a las posibilidades.

De todos modos, aprecié la perspectiva de los novatos sobre el asunto. Nos mantiene a todos frescos ...

Cuestiones relacionadas