1

I faced this error while deserialization a custom object I am trying to insert a collection of custom class into sql database & retrieve it the insertion going well but retrieving the data & deserialize give me this error My code sample:

        private void InsertObject()
    {
        ReceiptCollection items = SqlDataRepository.ReceiptProvider.GetAll();

        string connectionString = "my connection";

        System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);

        string sql = "INSERT INTO [dbo].[LogHeader]([MasterObject]) VALUES (@MasterObject)";

        BinaryFormatter binaryFormatter = new BinaryFormatter();
        MemoryStream memoryStream = new MemoryStream();
        binaryFormatter.Serialize(memoryStream, items);

        using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
        {
            byte[] bytes = new byte[memoryStream.Length];
            memoryStream.Write(bytes, 0, bytes.Length);

            connection.Open();
            cmd.Parameters.AddWithValue("@MasterObject", bytes);
            cmd.ExecuteNonQuery();
        }
    }

    private void RetrieveObjects()
    {
        string connectionString = "my connection";
        System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);

        string sql = "Select MasterObject From [dbo].[LogHeader] WHERE LogHeaderID=2";

        using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
        {
            connection.Open();
            byte[] bytes = (byte[])cmd.ExecuteScalar();

            BinaryFormatter binaryFormatter = new BinaryFormatter();
            MemoryStream memoryStream = new MemoryStream(bytes);
            memoryStream.Position = 0;
            ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream); // the error happened here
        }
    }
Mohamed
  • 109
  • 1
  • 3
  • 12

2 Answers2

2

I was facing the same problem in the serialization and deserialization of a custom class. Everywhere I looked around, they have the same code marked as the solution (as your code presented on the top) but I couldn't make it run correctly. All I was recieving after the memoryStream.Write() method, was an array of zeroes. I changed my code and got it to work.

What I did was (implemented in your code):

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    MemoryStream memoryStream = new MemoryStream();
    binaryFormatter.Serialize(memoryStream, items);

    using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
    {
        byte[] bytes = new byte[memoryStream.Capacity];
        bytes = memoryStream.GetBuffer();

        connection.Open();
        cmd.Parameters.AddWithValue("@MasterObject", bytes);
        cmd.ExecuteNonQuery();
    }

This is for sending a byte array to the data base. For retrieving it, I did the following:

    connection.Open();
    byte[] bytes = (byte[])cmd.ExecuteScalar();

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream(bytes))
    {
        memoryStream.Position = 0;
        ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream);
    }

Try it! It really worked for me.

1

Start by checking what actually got stored in that column, and also check if the column's type is varbinary or similar. The error suggests that the serialized object's data stream got badly corrupted or truncated. If the row/column does not contain a long "hexstring", then there's a write problem with inserting/updating and search further there.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • Thanks for your response, I am using VarBinary(MAX) field, And the column contains only – Mohamed Jun 17 '13 at 12:40
  • How can I check if my binary data is corrupted or not ? – Mohamed Jun 17 '13 at 12:50
  • When I select from the table I found the result like "0x000000000000000000000000000000000000000000000000" – Mohamed Jun 17 '13 at 13:06
  • This clearly means that at the time of INSERT or UPDATE some data was sent to that column, but that data consisted only of zeroes. In .Net world the simpliest way to get such thing is to create a buffer (a byte array, a MemoryStream etc) and set it to some size (ie. 32kB) and then .. forget to write data to it. Rerun your code that performs serialization and writes to the database, and put a breakpoint on `memoryStream.Write(bytes, 0, bytes.Length);`. Step-over that line and check if `bytes` array really is full of zeroes. – quetzalcoatl Jun 17 '13 at 17:53
  • If the array is all-zeroes, then either the serialization has failed, or the `memoryStream.Write` for some reason has not copied the data to the array. On the other hand, if the array contains something, then it means that everything was OK and that the SqlCommand failed to properly read the Parameter of `byte[]`. In that case, just to be sure, you might want to specify the DBType explicitely - try to set the parameter as in http://stackoverflow.com/a/1088630/717732 - but I have no idea why would it fail. `byte[]` is a simple type with no difficult mapping and it should default to varbinary – quetzalcoatl Jun 17 '13 at 17:55
  • Yes, I found the array contains only zeros, I will try with other simple objects to see if the problem on my object or not, but is there another way to save an objects in database? – Mohamed Jun 18 '13 at 06:57
  • There are three: you may either serialize/deserialize it as single oclumn, or decompose the object into simple values and save them as separate columns (Person -> {name,family,age,shoesize} -> pers_name,pers_fam,pers_age,pers_shoe), or you can use any ORM (EF,LINQ,NH,ADO,XPO,..) to do it for you (almost)automatically. – quetzalcoatl Jun 18 '13 at 07:30
  • I went to the XML serialization & it is working fine now, Thanks – Mohamed Jun 18 '13 at 10:42