De-serialization error after minor CSLA upgrade (3.0.2 - 3.0.4)

De-serialization error after minor CSLA upgrade (3.0.2 - 3.0.4)

Old forum URL: forums.lhotka.net/forums/t/5491.aspx


rsbaker0 posted on Monday, September 29, 2008

I've run into an apparent snag trying to reload an object created when we were using a different version of CSLA. The object was serialized to binary and saved in the database, but when I try to reinstantiate it, I get this error:

Could not load file or assembly 'Csla, Version=3.0.2.0, Culture=neutral, PublicKeyToken=93be5fdc093e4c30' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

We're using Csla 3.0.4 now, but I was surprised to see that just this minor upgrade could cause this.

Any thoughts as to why I might be seeing this? It looks like there may be some perils to just serializing things out of convenience that we hadn't anticipated.

 (A potential side issue is that I don't even see how the object I'm restoring even would reference CSLA, since there are no CSLA base classes in it's parent hierarchy or of its members, but that's a another story).

ajj3085 replied on Tuesday, September 30, 2008

Well, it's a BO you've serialized right?  So BusinessBase had it's fields serialized as well.  There's a way to configure the binary serializer to ignore version information.  That might work.. but this is the main reason that it's recommended NOT to store serialized BOs anywhere for any length of time.

rsbaker0 replied on Tuesday, September 30, 2008

No, but that's part II of the mystery. It's a very simple class with no parent in the CSLA framework:

[Serializable()]

public class CachedColumnList : List<CachedColumn>

Neither class has anything to do with CSLA - these are U/I classes just for remembering how a user had arranged the width and order of columns in a grid. (CachedColumn has no base class).

You offer some good advice though. I guess if you want to serialize something that needs to survive version changes, that you need to write your own custom serialization instead of just relying solely on the binary serializer. Seems like a shame, though. :(

ajj3085 replied on Tuesday, September 30, 2008

Hmm... mystery indeed.  The serializer stores assembly version information, but I wouldn't think it would store that assemblies dependencies... although perhaps it did.  Does your cached column class live in an assembly that references Csla?  maybe it does store that...

At any rate.. the serialization is meant to move .Net objects across a wire, not for persistence.  If you view serialization in that context, it makes sense.  The version information is included because maybe in 1.0 there was FieldB, but in your next version of the assembly is 1.1, and FieldB is gone, and FieldC is now included.  What's the serializer to do?  Well, you can configute it to ignore versions... but you're instancated object is now not valid.  FieldB's value is lost, and C will have the defaut value..

So, I'm not sure how I'd think you shoudl proceed, but that's the problem anyway...

Were you able to find the .config setting to ignore the version on deserialization?  If the class hasn't changed, you should be fine. 

rsbaker0 replied on Tuesday, September 30, 2008

ajj3085:
... Does your cached column class live in an assembly that references Csla?  maybe it does store that...

At any rate.. the serialization is meant to move .Net objects across a wire, not for persistence.  If you view serialization in that context, it makes sense.  The version information is included because maybe in 1.0 there was FieldB, but in your next version of the assembly is 1.1, and FieldB is gone, and FieldC is now included.  What's the serializer to do? 

Were you able to find the .config setting to ignore the version on deserialization?  If the class hasn't changed, you should be fine. 

Yes, the assembly itself references CSLA, so this was probably it.

Thanks for the insight -- I'm very glad I opened this can of worms early rather than once we had this in production.

In cases where I was using serialization for persistence, I was generally using a dictionary-derived class for the persisted data, that way it would just be a generalized Bag that I could put anything into it that I want.

I thought this would protect me from issues like this, but of course you could store any serializable class there, which opens up your FieldB, FieldC scenario with the contained objects. Back to the drawing board...

 

 

sergeyb replied on Tuesday, September 30, 2008

If you really have to find a way to persist, you can use (cannot believe I am saying this : - ))  data sets in conjunction with DataMapper to populate them off the objects.

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: rsbaker0 [mailto:cslanet@lhotka.net]
Sent: Tuesday, September 30, 2008 3:37 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] De-serialization error after minor CSLA upgrade (3.0.2 - 3.0.4)

 

ajj3085:

... Does your cached column class live in an assembly that references Csla?  maybe it does store that...

At any rate.. the serialization is meant to move .Net objects across a wire, not for persistence.  If you view serialization in that context, it makes sense.  The version information is included because maybe in 1.0 there was FieldB, but in your next version of the assembly is 1.1, and FieldB is gone, and FieldC is now included.  What's the serializer to do? 

Were you able to find the .config setting to ignore the version on deserialization?  If the class hasn't changed, you should be fine. 

Yes, the assembly itself references CSLA, so this was probably it.

Thanks for the insight -- I'm very glad I opened this can of worms early rather than once we had this in production.

In cases where I was using serialization for persistence, I was generally using a dictionary-derived class for the persisted data, that way it would just be a generalized Bag that I could put anything into it that I want.

I thought this would protect me from issues like this, but of course you could store any serializable class there, which opens up your FieldB, FieldC scenario with the contained objects. Back to the drawing board...

 

 



RockfordLhotka replied on Tuesday, September 30, 2008

rsbaker0:

I guess if you want to serialize something that needs to survive version changes, that you need to write your own custom serialization instead of just relying solely on the binary serializer. Seems like a shame, though. :(

This is absolutely true!! Microsoft recommends against using the BinaryFormatter or NetDataContractSerializer for any sort of persistence. These formatters should only be used for transient data, because the versioning consequences can be very serious if you change your assemblies while serialized data is outstanding.

Copyright (c) Marimer LLC