Xml Serialization questions

Posts   
 
    
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 20-Mar-2015 16:50:24   

I'm investigating using XmlSerialization in LLBLGen because I need to persist an entity collection and there is a chance that the database schema might be changed when it is read back again.

Two questions:- 1) Will Xml deserialization work if, from the new schema, (a) a field has been added, (b) a field has been removed? 2) Was it intentional or an oversight that LLBLGen XmlSerialization serializes readonly properties? (I know I can use XmlIgnoreAttribute but there are too many additional properties to do that and .NET xml serialization spec ignores properties with a setter automatically)

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 20-Mar-2015 19:24:49   

1)Deserialization will work except if a field was removed. 2)Why serializing read-only properties is a problem?

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 22-Mar-2015 18:39:54   

Thanks for (1) Walaa.

For (2), an exception will surely have to be thrown if there is no setter - that's why XmlSerializer doesn't even bother to try serializing properties that don't have both a getter and a setter.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 23-Mar-2015 04:02:00   

simmotech wrote:

For (2), an exception will surely have to be thrown if there is no setter - that's why XmlSerializer doesn't even bother to try serializing properties that don't have both a getter and a setter.

I don't see that as a problem. Anyway, if you want to put XmlSerialization attribute to any read-only field, you can do it via a plugin or writing a template that emit such annotations. For more info read the SDK docs ( http://www.llblgen.com/documentation )

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 23-Mar-2015 10:08:22   

It doesn't check for readonlyness of the property but as at runtime the descriptor is a reflectpropertydescriptor, it's taken care of (i.e. calling SetValue on the descriptor shouldn't cause an exception).

The data is serialized as it might be the xml document is used elsewhere than for deserialization and thus the data is part of the object and thus has to be serialized

Frans Bouma | Lead developer LLBLGen Pro
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 08-Dec-2016 10:24:05   

Late reply.... Well, I went with FastSerialization because we decided we were sure the schema wouldn't need to change but of course it did and so we now have to use safer Xml serialization. disappointed

The data is serialized as it might be the xml document is used elsewhere than for deserialization and thus the data is part of the object and thus has to be serialized But why couldn't it been an option in XmlFormatAspect?

I can apply attributes I guess but if I miss one by mistake, I won't know about it until it is too late! As I've just found out cry

Now I realize that I am still on v4.2 and things may have changed since then - have they?

Another possible solution would be to override Entity2Xml as you mentioned in another ticket somewhere but pasting the existing code showed that XmlHelper.WriteRelatedObjectElement and GetInheritanceHierarchyType() and IXmlCollectionSerializable are all marked internal.

Any other suggestions?

Cheers Simon

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 08-Dec-2016 13:05:31   

simmotech wrote:

Late reply.... Well, I went with FastSerialization because we decided we were sure the schema wouldn't need to change but of course it did and so we now have to use safer Xml serialization. disappointed

The data is serialized as it might be the xml document is used elsewhere than for deserialization and thus the data is part of the object and thus has to be serialized But why couldn't it been an option in XmlFormatAspect?

I can apply attributes I guess but if I miss one by mistake, I won't know about it until it is too late! As I've just found out cry

You can add attributes based on rules in the project settings. I'd use these first. THe rules make sure all elements matching them (now or in the future) will get the attributes. So you don't need to manually define them on each element.

Now I realize that I am still on v4.2 and things may have changed since then - have they?

xml serialization hasn't change since 2.5 (the formats that is) and that'll stay the same as these formats are important for backwards compatibility. If you opt for 'verbose' types might change, but using 'verbose' isn't recommended anyway. XML Serialization in general works best with the compact25 format which is the default, which gives plain xml with values.

Another possible solution would be to override Entity2Xml as you mentioned in another ticket somewhere but pasting the existing code showed that XmlHelper.WriteRelatedObjectElement and GetInheritanceHierarchyType() and IXmlCollectionSerializable are all marked internal.

You refer to solution, but not what the actual problem it is a solution for. The built-in xml serialization code works OK, just serialize the graphs and you get xml. If you want it in a different format, write some xlst and transform it into something else (that's what it's for! wink )

I don't see a reason why anyone would want to override these methods: don't do that, simply let the framework serialize the data.

Frans Bouma | Lead developer LLBLGen Pro
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 08-Dec-2016 15:20:38   

I don't see a reason why anyone would want to override these methods: don't do that, simply let the framework serialize the data.

Well you did ask... smile

I wanted to override the methods for several reasons:

1) It serializes too much. ReadOnly properties should not have be serialized by default IMHO. You make a valid point about it actually being an XMLDocument that could be used for purposes other than serialization but an option on XmlFormatAspect to turn that on when required would have been better. As you say too late to change that now.

2) Your point about attributes based on project settings doesn't apply here. Serializing the generated entities is (I assume) all fine but, for actual usage, I have partial classes for virtually all entities and none of the additional properties on these have attributes because they weren't necessary until now.

3) It serializes properties with no value - e.g. "<LatestValuation></LatestValuation>"

4) It serializes properties where there is no prospect of deserialization (or can have no use in an XmlDocument) e.g.

        [Browsable(false), XmlIgnore]
        public PartyListNameFormatter PartyListNameFormatter { get; set; }

is on several of my entities. It serializes as "<PartyListNameFormatter>TIPS.DAL.EntityClasses.PartyListNameFormatter</PartyListNameFormatter>" and, worse, bombs on deserialization because a string cannot be converted back to a PartyListNameFormatter.

5) I don't want to change the Xml format per se - Compact25 is fine. I am an old man now and way too old to be dealing with serialization again! I just wanted a bit of control so that I could prevent serializing that which didn't need to be serialized.

If this code in Entity2Xml:

            else if (!uniqueFieldNames.Contains(properties[index].Name))
            {
              writer.WriteStartElement(properties[index].Name);
              XmlHelper.WriteValueAsStringToXml(properties[index].PropertyType, properties[index].GetValue((object) this), verboseXml, !flag2, writer, datesInXmlDataType, mlInCDataBlocks);
              writer.WriteEndElement();
            }

had just called a virtual bool ShouldXmlSerialize(PropertyDescriptor) method and skipped if false is returned then I could have done everything I need in there.

As it is, I now have to visit 113 partial entity classes (plus at least 1 template) to add XmlIgnore attributes on hundreds of properties. My biggest problem is item 4 - if I miss an attribute accidentally now or in the future and it gets serialized then it is not possible to read that graph back again.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 09-Dec-2016 10:39:46   

Preventing something is serialized is done by adding the attribute. Yes this is cumbersome in hand-written code, but there's no other way by default. It's your code, you have to deal with the serialization of it, the same way I have to deal with serialization of data inside my code by implementing IXmlSerializable.

Anyway, for serialization, you can also apply the attribute CustomXmlSerialization. This attribute makes the serializer emit the start/end elements and then call PerformCustomXmlSerialization. You can override that method in a partial class of CommonEntityBase and do your serialization thing. Or ignore it.

For deserialization there's a similar method. If the target property (the property to write the data into) is marked with CustomXmlSerialization, for deserialization the framework will call PerformCustomXmlDeserialization.

This way you can add your own serialization with the framework. The best way to do that is by simply implementing IXmlSerializable on your own objects so you can call into that if one of these methods is called.

that's what I can offer you.

Frans Bouma | Lead developer LLBLGen Pro