Oct 30, 2012

Xml Serializer - Deserialization - basics


Collection of bussines objects in XML should be deserialized in collection of DTO objects using .NET XmlSerializer.
Although it is normal in such scenario to have XSD schema that explains XML will assume that you can't obtain one but have to manually write DTO's that reflect data in XML.

Here is collection of bus.objects in plain XML:

<Products>
<Product>
<Id>1</Id>
<Name>Tommato</Name>
</Product>
<Product>
<Id>2</Id>
<Name>Apple</Name>
</Product>
</Products>

Firstly we have to tweak above since it is not acceptable for XmlSerializer.
When working with collections we must envelope collection node with an extra node serving as container like this:
<ProductCollection>
<Products>
<Product>
<Id>1</Id>
<Name>Tommato</Name>
</Product>
<Product>
<Id>2</Id>
<Name>Apple</Name>
</Product>
</Products>
</ProductCollection>

Writing DTO


Here is DTO:


[Serializable()]
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    [Serializable()]  
    public class ProductCollection
    {      
        public Product[] Products;
    }  

It is not common to write your own DTO's. You should have XSD schema provided and then consider using XSD.EXE to generate your objects.
Observe how objects are clear from attributes.
DO NOT needlesly decorate your DTO with XML attributes unless neccessary.

Bellow code will perform absolutly the same. Added atributes serve only to developer as comments not XmlSerializer. He is perfectly capable to reflect simple DTO's.

[Serializable()]  
    public class Product
    {
        [XmlElement("Id")]
        public int Id { get; set; }
        [XmlElement("Name")]
        public string Name { get; set; }
    }
    [Serializable()]
    [XmlRoot("ProductCollection")]
    public class ProductCollection
    {
        [XmlArray("Products")]
        [XmlArrayItem("Product")]
        public Product[] Products;
    }  

Here is one of proper ways of using attributes. Let's assume that my DTO objects and XML input have different naming of fields or even parent node. In this sample XML field "Name" is mapped to DTO's "ProductName" and XML parent node "ProductCollection" is mapped to our DTO ProductsContainer.

[Serializable()]  
    public class Product
    {  
        public int Id { get; set; }
        [XmlElement("Name")]
        public string ProductName { get; set; }
    }
    [Serializable()]  
    [XmlRoot("ProductCollection")]
    public class ProductsContainer
    {      
        public Product[] Products;
    }  

Writing deserialization


Let's write simplest deserialization for above sample. Note that this code matches last version of DTO's with name mappings.

       private static ProductsContainer GetProductsFrom(string xml)
        {
            using (TextReader textReader = new StringReader(xml))
            {
                var serializer = new XmlSerializer(typeof(ProductsContainer));
                ProductsContainer results = serializer.Deserialize(textReader) as ProductsContainer;
                return results;
            }          
        }
Serializer expect two things: prepared stream with XML content (either from file or plain string like in my case) and secondly type of object we try to deserialize.

Handling nullable or empty values in XML


In real life we can receive empty values for fields content or even complete field can be missing.
For example:

<ProductCollection>
<Products>
<Product>
<Id></Id>
<Name>Tommato</Name>
</Product>
<Product>
<Id>2</Id>
<Name></Name>
</Product>
</Products>
</ProductCollection>

In this sample Id from first and Name from second element is empty.
Of course empty string is completely valid value for String element. Although one could ask how to get NULL value not "" as a result.
This empty Id is problem since conversion from NULL -> Int is not possible.

Let's tweak Product DTO allowing nullable integer:

...
public class Product
    {
        public int? Id { get; set; }
...

That's our side but it is not problem solver. Serializer will not treat empty content or in that manner any other content which is not convertible to Int as NULL. Why would he? Change your mindset - yes he sees NOT empty but non-convertible value and he will complain about it. If you had instead  :
...
<Product>
<Id>foo</Id>
...
; it would still raise error.
Your provider of XML has to handle this too. Again commonly this is stated in XSD schema accepted by both sides as contract.
If no XSD then your provider must explicitly write like this:
...
<Product>
<Id xsi:nil="true"></Id>
...
Additionally on header of root element provide reference to XML schema language like this:
...
<ProductCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
Otherwise XML Serializer won't know what xsi attribute stands for.

Handling missing value


So what about completly missing fields like this:

<ProductCollection>
<Products>
<Product>
<Id>1</Id>
<Name>Tommato</Name>
</Product>
<Product>
<Name></Name>
</Product>
</Products>
</ProductCollection>

Allowing for nullable types in your DTO will do it. We did it already above with this:
...
public class Product
    {
        public int? Id { get; set; }
...
When XML Serializer bumps on missing field he checks your DTO and sees that nullable is allowed. Ok by him.


Deserializing 1:MANY entity



How about a litle bit more complicated example. Let's assume Order contains collection of products. Here is XML input:

<?xml version="1.0" encoding="utf-8" ?>
<Order>
  <Id>1</Id>
  <Name>Order one</Name>
  <Products>
    <Product>
      <Id>1</Id>
      <Name>Apple</Name>
    </Product>
  </Products>
</Order>

And here is DTO's. Very clean and logic:

    [Serializable()]
    [XmlRoot("Order")]
    public class Order
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Product[] Products;
    }
    [Serializable()]
    public class Product
    {
        public int? Id { get; set; }
        public string Name { get; set; }
    }


Handling XML node attributes



In real life we can have price for our product described in XML like this:

<Product> <Id>1</Id> <Name>Apple</Name> <Price Currency="€" Taxdeductable="true">2.23</Price> </Product>

Value of currency and taxdeduction are described as attributes. This is how we describe it in DTO's:

  [Serializable()]
    [XmlRoot("Order")]
    public class Order
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Product[] Products;
    }
    [Serializable()]
    public class Product
    {
        public int? Id { get; set; }
        public string Name { get; set; }      
        public PriceElement Price { get; set; }
    }
    [Serializable()]
    public class PriceElement
    {
        [System.Xml.Serialization.XmlTextAttribute()]
        public double Value { get; set; }
        [XmlAttribute("Currency")]
        public string Currency { get; set; }
        [XmlAttribute("Taxdeductable")]
        public bool Taxdeductable { get; set; }
    }


Handling XML namespaces



In our samples we work with orders. It is quite realistic that we could get orders from more than one company.
Also it is quite possible that both companies provide us with entites named Order. In such case in XML we use XML namespaces to differ two Order entities
since XML syntax does not allow for two Order elements with different structure.
Here is XML document:

<?xml version="1.0" encoding="utf-8" ?>
<Catalog>
  <myorders:Order xmlns:myorders="http://www.myorders.com/ordercatalog">
    <myorders:Id>1</myorders:Id>
    <myorders:Name>Order one</myorders:Name>
    <myorders:Products>
      <myorders:Product>
        <myorders:Id>1</myorders:Id>
        <myorders:Name>Apple</myorders:Name>
        <myorders:Price Taxdeductable="true">2.23</myorders:Price>
      </myorders:Product>
    </myorders:Products>
  </myorders:Order>
  <croatiaorders:Order xmlns:croatiaorders="http://wwww.croatiaorders.com">
    <Id>23</Id>
    <Name>Pear</Name>
  </croatiaorders:Order>
</Catalog>

Observe that myorders prefix is applied to all elements of myorders:Order. That way all its elements are consistently assigned to myorders xml namespace.
Second order is not all prefixed. Only parent element croatiaorders:Order is prefix. It's items Id & Name are not prefix. This is perfectly legal by XML syntax but not expected by parsers as we shall see.
Our existing entity Order belongs now to xml namespace defined in http://www.myorders.com/ordercatalog.
Second order came from company whose XML namespace is defined in http://wwww.croatiaorders.com
New Catalog entity is added as simple container for both orders.
Let's look at changes in DTO's:

    [Serializable()]
    [XmlRoot("Catalog")]
    public class Catalog
    {
        [XmlElement(Namespace = "http://www.myorders.com/ordercatalog")]
        public Order Order { get; set; }
        [XmlElement("Order", Namespace = "http://wwww.croatiaorders.com")]
        public CroatiaOrdersOrder CroatiaOrdersOrder { get; set; }
    }      
    [Serializable()]
    public class Order
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Product[] Products;
    }
    [Serializable()]
    public class Product
    {
        public int? Id { get; set; }
        public string Name { get; set; }      
        public PriceElement Price { get; set; }      
    }
    [Serializable()]
    public class PriceElement
    {
        [System.Xml.Serialization.XmlTextAttribute()]
        public double Value { get; set; }
        [XmlAttribute("Currency")]
        public string Currency { get; set; }
        [XmlAttribute("Taxdeductable")]
        public bool Taxdeductable { get; set; }
    }
    [Serializable()]
    public class CroatiaOrdersOrder
    {
        [XmlElement(Namespace="")]
        public int Id { get; set; }
        [XmlElement(Namespace = "")]
        public string Name { get; set; }
    }

Our original Order (myorders.com) is decorated with :

[XmlElement(Namespace = "http://www.myorders.com/ordercatalog")]

Note that child elements of myorders.com by default inherit namespace. No further decorating with attributes is neccessary.
So if in XML you consistently use your namespace in all child elements, like we did for myorders:Order, we're done.
On the other hand if in XML you ommit xml prefix for child elements of parent that has declared xml namespace, like we did for CroatiaOrders, then you must explicitly decorate each child element with :

[XmlElement(Namespace="")]

; in order to work with XMLSerializer. Otherwise you wont have errors but NULL values.


And if you ran on problems some good reading:

http://www.codeproject.com/Articles/14064/Using-the-XmlSerializer-Attributes
Troubleshooting Common Problems with the XmlSerializer

Oct 29, 2012

What is POCO & DTO?

Sooner or later after years of working as .NET developer ,without no aspirations to become architect :),  you get hit by this or that pure architecture jargon from your coworker (doing a lot of overnight reading and with aspiration to become architect :) ) or your boss.

Well it happens to once in a while.

So what is POCO?  " Hey, just do plain POCO's object no big deal, OK ? Got it?"

Been there ?

Yea, you try to hide stupid expression from your face and node with your head like you know what is it.
Few developers got guts to simple ask explanation from dude that speaks like that.

One thing you can be sure is that person thinks highly off you :) considering you have more than basic .NET architectural expirience.
POCO & DTO as terms that relay above simple old multi-layer architecture.
Yes they are both .NET classes. So what?

How many times have you decorated your objects for serialization?
Or how many times have you created partial classes to extend  LINQ or EF entities ?
Or writing highly custom WCF contracts and etc?

Well as average developer you do this and that with objects but you don't spend to much time naming what you do. You don't dwell in deeper understanding on what architecture principles lies EF or WCF.
We simply use it, right?

But than it comes to those 1 out of 100 situations. You use WCF, LINQ on everyday bases and BAM you run in to problem. Things don't work as you expected. Been there?
Suddenly its not enough to only know exposed API model - load, save, update, fetch bla bla.
As every normal dude you need to google solution, but how ?

That's my point, average developer today should get introduced to basic architectural terminology so you can google or ask your fellow architect and buy him a coffee.

Back to subject... Plain and simple POCO is good old OO class. You DO NOT decorate it with attributes.

In vision of accepted DDD (Domain driven design) approach it should be in very heart of your domain or business logic (onion architecture).
The catch is that you DO NOT make it dependant on your ORM for example.
And NO it is not just STATE or data container that is DTO.
POCO is full fledged sovereign object that describes in both behavior and content given real world problem.
And it does NOT KNOW how to save itself.

To repeat myself, POCO objects ideally should be in very heart of your project / domain you describe and not dependent on outer architecture that service them.

And what about DTO?
Now that is something you simply use to transfer data. They are flat. Way I see it put in .NET terms DTO are structures (which does not mean that DTO's should be coded as Structure ! ) . They only relay STATE or data NO BEHAVIOR

As stated bellow you could use them for example to service POCO's needs to "talk to world" by describing some data or frequently in web services as quick containers.

http://stackoverflow.com/questions/725348/poco-vs-dto

Oct 12, 2012

T-SQL order incorrect with dash charachter?

For those impatient read this: http://social.msdn.microsoft.com/Forums/en/transactsql/thread/a2785ed0-2355-43f3-bd8b-2200824e9c1f

 Now, this one is interesting...

After 8 years of SQL I'm still learning how to ... ORDER ?!

Check this out:


declare @mytable as table(name varchar(20))
insert into @mytable VALUES('FR-I')
insert into @mytable VALUES('FRieR')
insert into @mytable VALUES('FR-R')

select name from @mytable order by name 


The result is incorrectly ordered:

FR-I
FRieR
FR-R

What ?
 What's wrong, why is FRieR befoer FR-R ?

Aha, you figure it out ... It's the unicode of course.
Let' just use good ol' NVARCHAR and problem solved. Right?
Let's see:

declare @mytable as table(name nvarchar(20))

Nop, still incorrectly ordered...

Hmmm....

Oh yea its probably some collation mismatch, let's use explicit collation in ORDER clause:



select name from @mytable order by name COLLATE Latin1_General_CI_AS

Still not working ? But why oh why.

BTW 
In collation value Latin1_General_CI_AS last chars are VERY important 
CI - Case insensitive 
AS - Accent sensitive 
 or 
CS - Case sensitive 
AI - Accent sensitive 

Here is the solution:

select convert(nvarchar,name) as name from @mytable order by name COLLATE Latin1_General_BIN 

It's interesting that problem shows face only in quite special case like with char '-'.
Try '+' and no problem.
 As always at some point you can't take stuff for granted like ORDER.

"The day you stop learning is the day you die..."


 So remmeber : COLLATE Latin1_General_BIN is your best friend :)