Serialization and Deserialization

A

Amadelle

Hi all and thanks in advance for your help,

I am having problems deserializing an object which seems to be serializing just fine. I save the byte array of the serialized object in the database (when I check the database the field that holds the binary data seems populated), but when I want to deserialize this same byte array the application fails and gives me the following error:

Binary stream does not contain a valid BinaryHeader, 0 possible causes, invalid stream or object version change between serialization and deserialization.

Here is the code that I am using for serialization:

//Serialization of the FilterManager object and saving the binary data in the database
public int SaveFilterUser (int userID, string filterName, FilterManager mgr)
{
DatabaseContext objContext = null;
try
{
// Serialization
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms=new MemoryStream();
bf.Serialize(ms,mgr);
ms.Seek(0,0); // Return stream to start ?
ms.Position = 0; //Return to start
byte [] byteArray = ms.ToArray();
ms.Flush();
ms.Close();

//The rest of the Code here basically saves the byteArray generated to the database
FilterUser filterUser = new FilterUser();
filterUser.UserID = userID;
filterUser.SavedFilterName = filterName;
filterUser.FilterObjects = byteArray;
objContext = new DatabaseContext(false, strConn, strProvider);
FiltersUsersDalc objDA = new FiltersUsersDalc();
return objDA.Create (objContext, filterUser);
}
finally
{
if(objContext != null)
objContext.ReleaseConnection();
}
}

---------------------------------------------------------------------------------------------------
Here is the deserialization code:

///Deserialization of FilterManager object
public FilterManager GetFilterUser (int userID, string filterName)
{
DatabaseContext objContext = null;
try
{
//Get the binary data from the database based on username and filtername

objContext = new DatabaseContext(false, strConn, strProvider);
FiltersUsersDalc objDA = new FiltersUsersDalc();
FilterUser filterUser = objDA.GetFilterUser (objContext, userID, filterName);

//Basically Gets the byte Array back from the database and try to generate the Memory stream from it.
byte[] byteArray = filterUser.FilterObjects;
//Deserialize object
BinaryFormatter bf = new BinaryFormatter();
Stream ms=new MemoryStream(byteArray);
ms.Position = 0;
FilterManager mgr = (FilterManager) bf.Deserialize(ms); //###THE CODE FAILS HERE and returns the error message above.
ms.Flush();
ms.Close();
return mgr;
}
finally
{
if(objContext != null)
objContext.ReleaseConnection();
}
}

What am I doing wrong?

Any suggestions is appreciated,

Thanks,

Amadelle

One more thing: I am using the following code to get and set the binary data in the database (ofcourse I am not showing the whole code but how I set the parameters and how I get the results back)
To Get:
int bufferSize = 100;

byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes

long retval; // The bytes returned from GetBytes.

long startIndex = 0;

retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);


// Continue reading while there are bytes beyond the size of the buffer.

while (retval == bufferSize)

{

// Reposition the start index to the end of the last buffer and fill the buffer.

startIndex += bufferSize;

retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);

}

objFilterUser.FilterObjects = outbyte;



To Set:

aryParamList.Add("@FilterObjects", DbType.Binary, 50, objFilterUser.FilterObjects);
 
R

Robert Jordan

Hi Amadelle,
Hi all and thanks in advance for your help,

I am having problems deserializing an object which seems to be serializing just fine. I save the byte array of the serialized object in the database (when I check the database the field that holds the binary data seems populated), but when I want to deserialize this same byte array the application fails and gives me the following error:

Binary stream does not contain a valid BinaryHeader, 0 possible causes, invalid stream or object version change between serialization and deserialization.

Here is the code that I am using for serialization:

The serialization & deserialization code is ok, but ...

One more thing: I am using the following code to get and set the binary data in the database (ofcourse I am not showing the whole code but how I set the parameters and how I get the results back)
To Get:
int bufferSize = 100;

byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes

long retval; // The bytes returned from GetBytes.

long startIndex = 0;

retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);


// Continue reading while there are bytes beyond the size of the buffer.

that's wrong. use while (retval > 0 && retval <= bufferSize)
while (retval == bufferSize)

{

// Reposition the start index to the end of the last buffer and fill the buffer.

startIndex += bufferSize;

here startIndex += retval.
retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);

}

objFilterUser.FilterObjects = outbyte;



To Set:

aryParamList.Add("@FilterObjects", DbType.Binary, 50, objFilterUser.FilterObjects);

bye
Rob
 
A

Amadelle

Ok this was a good suggestion, still didn't solve my problem though ..
I think you are absolutely right though Robert in the fact that the part
that I am messing up is getting the binary data from the database.
Several things that I noticed:
1- When I serialize the object the byte array that I generate has a size
(length) of 2700+. But when I get the array of bytes back it is only the
buffer size of 100
so the outbyte is never larger than the 100 which makes sense since I have a
line of code byte[] outbyte = new byte[buffersize] and buffersize being 100
explains why the lengths are never the same. So i tried to fix this problem
by using the buffer size of 8000. But even extending the buffer size didn't
solve my problem. So given my code, it seems that I am still not populating
the array of bytes correctly (I used your code change suggestions but that
didn't solve my problem either).
2- Next step .. I noticed that all of the array items in the byte array
generated after the serialization usually have a value in the form of number
associated with them. so for example arrBytes[2] has a value of 255. But
when I get the array back regardless of the size (100 vs. 2700), even the
first 100 all come back with values of 0. Further, in the code, I use a
variable called retval which is supposed to represent the bytes returned
from the GetBytes method of datareader. This retval always comes back with
a value of 1. So the loop for going from retval to buffer size pretty much
stops after the first round.

In the database I am using varbinary to store this binary data, and I know
that the size of this field is only 8000 bytes max. So here is the part
that I get fuzzy. I am not so sure whether my data gets cut down due to the
field limitations in SQL .... or am I doing something else wrong in the
calls that I make to read the data back from the database?

This is too complicated and I don't really understand the binary data and
how the sizes work in relation to the byte array, data type var binary, how
to read it back, etc. So any help would be great... if someone can also
direct me to the right location, documentation to read up on the issue as
well, that would be great too..

Thanks again in advance,

Amadelle


Robert Jordan said:
Hi Amadelle,
serializing just fine. I save the byte array of the serialized object in
the database (when I check the database the field that holds the binary data
seems populated), but when I want to deserialize this same byte array the
application fails and gives me the following error:invalid stream or object version change between serialization and
deserialization.
The serialization & deserialization code is ok, but ...
data in the database (ofcourse I am not showing the whole code but how I set
the parameters and how I get the results back)
To Get:
int bufferSize = 100;

byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes

long retval; // The bytes returned from GetBytes.

long startIndex = 0;

retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);


// Continue reading while there are bytes beyond the size of the buffer.

that's wrong. use while (retval > 0 && retval <= bufferSize)
while (retval == bufferSize)

{

// Reposition the start index to the end of the last buffer and fill the buffer.

startIndex += bufferSize;

here startIndex += retval.
retval = objDataReader.GetBytes((int)ColumnIndex.FilterObjects, startIndex, outbyte, 0, bufferSize);

}

objFilterUser.FilterObjects = outbyte;



To Set:

aryParamList.Add("@FilterObjects", DbType.Binary, 50, objFilterUser.FilterObjects);

bye
Rob
 
R

Robert Jordan

Hi Amadelle,
This is too complicated and I don't really understand the binary data and
how the sizes work in relation to the byte array, data type var binary, how
to read it back, etc. So any help would be great... if someone can also
direct me to the right location, documentation to read up on the issue as
well, that would be great too..

I never used the DB-stuff of the framework. However, the
usual idiom for pulling data from a reader is:

MemoryStream m = new MemoryStream();
byte[] buffer = new byte[8192];
long read;
long index = 0;

while ((read = objDataReader.GetBytes((int)ColumnIndex.FilterObjects,
index, buffer, 0, buffer.Length) > 0)
{
m.Write(buffer, 0, (int)read);
index += read;
}

bye
Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top