Otis wrote:
Barry wrote:
I try to serialize the tracker by overriding methods in EntityCollection<TEntity>, it only works if the collection has data.
Any workarounds? or I better not to use the tracker and handle the removed entities by myself?
What you ran into is exactly this thread:
http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=11007
It's really unfortunate though... If it was related to client side stuff only it wouldn't be a big problem, but it is related to code which requires the same version on both sides, and that thus depends on build numbers.
Another problem is that if the trackers are serialized by default, it's extra data for the users who use unitofworks. This isn't that useful.
What you could do is add the tracker to a unitofwork for deletion, add the entities to process to the unitofwork for save and send that over the wire. I'm not sure if this meets your architecture.
I've been thinking a little about this problem and think I have a solution - albeit in two parts
(I've not tested this BTW - just looked at the source so there may be a problem I haven't foreseen but I'm reasonably confident
)
Firstly, if the next build could make one small library change, we could solve the problem of letting developers have an opportunity to serialize the tracker themselves manually.
The code changes is just to remove the " && memberEntityCollections[i].Count != 0" condition in FastSerializer.WriteEntityMemberCollections.
This change would have no impact on existing users except that a non-null but empty member collection would take a few extra bytes in the stream (I really mean a few - typically 2 for the collection flags, 1 for a string token plus the bytes required to store the string field name once). Build mismatches are not a problem because only the 'what' has changed, not the 'how'.
A change would also need to be made in the template (only for the developers wanting to manually serialize the tracker - not for general release) that creates the HasPopulatedMemberEntityCollections() method - just change so that the "Count > 0" condition is removed (or maybe leave it and add "&& _<membercoll>.RemovedEntitiesTracker != null && _<membercoll>.RemovedEntitiesTracker.Count > 0")
However, since the collection is now being serialized, mikeg and Barry now should have control in SerializeOwnedData and can deal with the tracker. This would require the same build on both client and server but I'm sure that won't be a problem for mikeg and Barry anyway. (BTW rather than using the WriteObject method as mentioned in this thread, you could probably create a new FastSerializer, serialize the tracker and then store the resulting byte[] into the stream of the passed SerializationWriter - nested FastSerialization if you will!)
The second part suggested is for the next version. This would involve changing the interface to add a bool property allowing the object to say whether it should be serialized or not - default implementation for EntityCollectionBase2 would then be "return Count != 0" thus getting back the saving on the few extra bytes from part one.
Plus template changes as mentioned above.
Then there is the issue of whether the tracker should be serialized by default or not. My opinion is that it probably should since I believe that serialization/deserialization should restore the entire object (with the exception of UnitOfWork since it has a flag giving the developer an option).
I understand the point about the tracker data being serialized twice if it is involved with a UnitOfWork but I believe this is easily got around by making the tracker an integral part of the collection - ie a bit flag to say whether one is present or not and adding a bit of code to ReferencedEntityMap to identify the tracker's entities as being referenced. That way, when incorporated into a UnitOfWork, only one instance will be stored with two references to it but if just in the collection, they are serialized inline.
Cheers
Simon