Преобразование массива byte[] в DataTable

Я сохранил объект типа DataTable в базе данных SQL 2005 в поле типа varbinary. Я хочу вернуть его обратно, но я не смог его ввести. Вот так я его сохранил.

MemoryStream memStream = new MemoryStream();
    StreamWriter sw = new StreamWriter(memStream);

sw.Write(dt);
con.Open();
using (SqlCommand cmd = new SqlCommand("INSERT INTO Tables(TableName, TableData, QuestionID) VALUES (@TableName, @TableData, @QuestionID)", con))
{
    cmd.Parameters.Add("@TableName", SqlDbType.VarChar).Value = "a new table";
    cmd.Parameters.Add("@TableData", SqlDbType.VarBinary,Int32.MaxValue).Value = memStream.GetBuffer();
    cmd.Parameters.Add("@QuestionID", SqlDbType.VarChar).Value = "2";
    cmd.ExecuteNonQuery();

}

«dt» — это экземпляр объекта DataTable.


person Ahmad Farid    schedule 19.08.2009    source источник


Ответы (4)


То, о чем вы говорите, - это двоичная сериализация и десериализация. Возможно, это поможет.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;
using System.Text;

namespace Serial
{
    public class Ser
    {
        public static byte[] StrToByteArray(string str)
        {
            UTF8Encoding  encoding = new UTF8Encoding ();
            return encoding.GetBytes(str);
        }

        public static string ByteArrayToStr(byte[] barr)
        {
            UTF8Encoding  encoding = new UTF8Encoding ();
            return encoding.GetString(barr, 0, barr.Length);
        }

        public static void Main(String[] args)
        {
            DataTable dt = new DataTable();
            DataRow dr;

            dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
            dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
            dt.Columns.Add(new DataColumn("DateTimeValue", typeof(DateTime)));
            dt.Columns.Add(new DataColumn("BooleanValue", typeof(bool)));

            for (int i = 1; i <= 1; i++) 
            {

                dr = dt.NewRow();

                dr[0] = i;
                dr[1] = "Item " + i.ToString();
                dr[2] = DateTime.Now;
                dr[3] = (i % 2 != 0) ? true : false;

                dt.Rows.Add(dr);
            }

            //Serialize
            BinaryFormatter bformatter = new BinaryFormatter();
            MemoryStream  stream = new MemoryStream();

            string s;
            bformatter.Serialize(stream, dt);
            byte[] b = stream.ToArray();
            s = ByteArrayToStr(b);
            stream.Close();
            dt = null;

            //Now deserialise
            bformatter = new BinaryFormatter();
            byte[] d;
            d = StrToByteArray(s);
            stream = new MemoryStream(d);
            dt = (DataTable)bformatter.Deserialize(stream);
            stream.Close();
        }
    }
}
person MyItchyChin    schedule 19.08.2009
comment
Какая польза от строки 'S'? - person Ahmad Farid; 19.08.2009
comment
@Ahmad: В этом примере DataTable сериализуется в byte[], затем кодируется как строка UTF8, затем обратно в byte[], затем DataTable. Поскольку вы храните байты в БД, это не имеет значения, но если вы хотите сохранить их как ntext или вставить в XML, вы бы это сделали. - person MyItchyChin; 19.08.2009

Боюсь, мне придется вас разочаровать, по крайней мере, до тех пор, пока вы не сообщите нам, что создали метод расширения для класса StreamWriter, который обрабатывает таблицы данных.

Единственная перегрузка метода Write, которая принимает экземпляр DataTable, — это та, которая принимает объект, и в соответствии с документация MSDN сохраняет только "текстовое представление" объекта.

Итак, будем надеяться, что метод .ToString класса DataTable выводит строку в формате, содержащем все содержимое экземпляра DataTable, но увы. Только метод .ToString возвращает содержимое свойства TableName и отображаемое выражение, если оно имеется.

Итак, вы сохранили не все содержимое экземпляра DataTable, а только имя таблицы.

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

person Lasse V. Karlsen    schedule 19.08.2009

Я предполагаю, что ваш код только что сериализовал таблицу данных, и вам нужно ее десериализовать. Я не знаю, какой форматер использовался, поэтому вам придется посмотреть на содержимое вашего двоичного поля. Если это двоичный файл, используйте BinaryFormater. (см. пример кода ниже). Если это не двоичный файл, попробуйте SoapFormatter и XmlSerializer.

person Daniel Brückner    schedule 19.08.2009

Возможно, вам лучше использовать XmlSerializer или BinaryFormatter для сериализации DataTable и последующего сохранения в двоичном столбце.

Ссылки для этого:
http://sadeveloper.net/forums/p/439/1772.aspx
http://bytes.com/topic/net/answers/428472-serializing-datatable

person Michael Todd    schedule 19.08.2009