• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 536
  • Last Modified:

Loss of object Info during serialization into sql server database in C# csharp .net

I think I am experiencing loss of information while serializing an object.
There is an object of type cMasterTest (parent), from which object of type cHP3245A_testParam (child) is derived. In other words, cHP3245A_testParam inherits cMasterTest.

I have been successful in storing nested serialized objects in an sql server database by inserting them into a memory stream, converting to an array of bytes, and storing them in a VARBINARY(MAX) field, and retrieving everything back.

This I would think would be simpler, but it doesn't seem to work: (Step 1) I take my object, explicitly cast it to its parent, then serializing that and storing it in a db. Then I (Step 2) retrieve the serialized object from the db, de-serialize it into the parent object, explicity cast it back to the child object.

Basically, once casting and inheritance is involved, I seem to have loss of information.

Please, if someone knows what is going on, please help me.
//*** (1) GET DATA ***\\
 
iHandleTests interfaceToUserControl =
                TDuc as iHandleTests;
 
// Here we are getting cHp3245A casted into cMasterTest and returned via
// the getTestParameters() method.
cMasterTest testParameters = interfaceToUserControl.getTestParameters();
 
/* The retrieval has been successfull because If I explicitly convert testParameters 
to cHP3245A_testParam object at this point there would be no loss of information, 
so I know I received the right data */
 
 
//*** (2) STORE DATA IN DATABASE ***\\
 
ms = new MemoryStream();
bf = new BinaryFormatter();
bf.Serialize(ms, testParameters);
sqlParam_data = new SqlParameter("@data", SqlDbType.VarBinary);
sqlParam_data.Value = ms.ToArray();
// sqlParam is then inserted to database
 
 
//*** (3) RETRIEVE DATA FROM DATABASE ***\\
 
sqlDataReader.Read();
bf = new BinaryFormatter();
ms = new MemoryStream((byte[])sqlDataReader["test_object"]);
cMasterTest cmt = (cMasterTest)bf.Deserialize(ms);
 
// PROBLEM HERE Conversion NOT successful -- Loss of information
cHP3245A_testParam tp = (cHP3245A_testParam)cmt;

Open in new window

0
yaronusa
Asked:
yaronusa
  • 4
  • 4
1 Solution
 
oobaylyCommented:
I assume the the loss of information are the properties in unique to cHP3245A_testParam, and the information succesfuly serialised is that which is defined in cMasterTest?

As you're casting the cHP3245A_testParam to cMasterTest, the serializer is only serialising the properties in cMasterTest (It doesn't know about the properties in cHP3245A_testParam).
0
 
yaronusaAuthor Commented:
Is there a way to make the parent object know about the child's info? If not, then I guess I will return a serialized version of the data, as opposed to a parent object which is then serialized.

So is there a way for the parent object to know about the child's info, to make it persistant so that when serialization takes place it knows? I'm guessing not....


0
 
oobaylyCommented:
Actually, just test a basic set of inherited classes, and if you serialize an object which has been casted to its parent class, there shouldn't be an issue. Apologies for that, I was thinking about the XmlSerializer's behaviour. I've also realised it Serializes private members too.

Have you tried serializing & deserializing without the rounds trip to the database, and verifying that that works. That way you can confirm the database storage isn't the issue.

Also, are you implementing your own serialization in this class?
      System.IO.MemoryStream ms = new System.IO.MemoryStream();
      BinaryFormatter sz = new BinaryFormatter();
 
      cMasterTest testParameters = interfaceToUserControl.getTestParameters();
      sz.Serialize(ms, testParameters);
 
      ms.Position = 0;
      cMasterTest cmt = (cMasterTest)bf.Deserialize(ms);

Open in new window

0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
yaronusaAuthor Commented:
I have successfully serialized to memory and de-serialized from memory without round trip to the database, so that works. In the code below you can see the test I ran.

Does this mean it is a database issue? I am using SQL Server 2005 Express. The name of the table is tblSerializedTests. The script that creates the table is in the code snippet.

The way I enter and retrieve the serialized info from the database, you can see that in my original posting above.

What other info can I give you or what's something else I can try?

One interesting note: When I serialize to the memory stream, it is of 724 length and 1024 capacity. But when I de-serialize, it is of length 725 and also 725 capacity. Not sure if that means anything, but I would expect the memory streams to be equal in length.



//*** SUGGESTED TEST (THIS WORKS) ***\\
MemoryStream ms2 = new MemoryStream();
BinaryFormatter bf2 = new BinaryFormatter();
bf2.Serialize(ms2, testParameters);
ms2.Position = 0;          
 
// Deserialize to parent
cMasterTest cmt = (cMasterTest)bf2.Deserialize(ms2);
 
 // Deserialize to child
 cHP3245A_testParam param = (cHP3245A_testParam)cmt; // Success!
// *** END OF SUGGESTED TEST ***\\
 
//*** DATABASE RELATED ***\\
-- Create test object table
CREATE TABLE tblSerializedTests
 (unique_id integer not null,
  test_name VARCHAR(25) not null,
  test_object VARBINARY(MAX) not null);
//*** END DATABASE RELATED ***\\

Open in new window

0
 
oobaylyCommented:
Very strange that the data being returned from the database is longer that the data inserted.
I've just tried serialising an object into a VARBINARY(MAX) field and the array returned is identical to that inserted.

Have you compared the byte array being inserted to the byte array being returned. Are they identical except the additional byte being returned?

I'd suggest running some tests on the table, ie inserting random lengths of data, and comparing the data returned.
0
 
yaronusaAuthor Commented:
The solution, it turns out, was quite simple. My SQL statement was not pulling the object I thought it was pulling from the database. The CLUE to this should have been the different in number of bytes going into the database then going out.

In any case, I resolved the SQL statement and it now works!!!

Thank you for leading me on the right path, I could not have done it without people like you.
0
 
yaronusaAuthor Commented:
The solution, it turns out, was quite simple. My SQL statement was not pulling the object I thought it was pulling from the database. The CLUE to this should have been the different in number of bytes going into the database then going out.

In any case, I resolved the SQL statement and it now works!!!

Thank you for leading me on the right path, I could not have done it without people like you.
0
 
oobaylyCommented:
No worries, glad to be of assistance.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now