WCF DataContracts

En los posts anteriores hemos llegado a ver la implementación de un servidor y cliente sencillos de WCF. Los datos que eran intercambiados eran clases del framework (int, string…), pero como intercambiar datos de mis clases (Clientes, proveedores…).

El CLR debe generar un esquema XML a partir de un tipo, es lo que se conoce con el nombre Data Contracts. El Data Contract describe como los tipos CLR son mapeados al esquema XML.

Al igual que ocurria con los servicios Web,  las clases que representan nuestras entidades con solo marcarlas con el atributo [Serializable] ya podrian ser expuestas por los servicios para que los clientes puedan consumirlas.

Y es cierto, funciona ya que la clase XMLSerializer sera la encargada de serializar la clase. Pero en WCF existe el sucesor de esta clase y es la clase XMLFormatter, que es la encargada de seralizar estos Data Contracts, la diferencia con la anterior es que es un 10% mas rapida, pero XMLSerializer nos da un control mas granular sobre la serialización de los objetos. XMLFormatter esta orientada a la rapidez que al control del desarrollador (esto sera estudio de algun post posterior)

Si antes marcaba la clase con el atributo [Serializable], ahora la debo marcar con el atributo [DataContract] y debo marcar los miembros que quiero que formen parte del mensaje con el atributo [DataMember].

Un ejemplo

DataContract(Namespace="http://schemas.thatindigogirl.com/2005/12/LinkItems", Name="LinkItem")]
public class LinkItem
{
  [DataMember(Name="Id", IsRequired=false, Order=0)] 
  private long m_id;
  [DataMember(Name = "Title", IsRequired = true, Order = 1)] 
  private string m_title;
  [DataMember(Name="Description", IsRequired = true, Order = 2)] 
  private string m_description;
  [DataMember(Name="DateStart", IsRequired = true, Order = 3)] 
  private DateTime m_dateStart;
  [DataMember(Name="DateEnd", IsRequired = false, Order = 4)] 
  private Nullable<DateTime> m_dateEnd;
  [DataMember(Name="Url", IsRequired = false, Order = 5)] 
  private string m_url;
  [DataMember(Name="LinkType", IsRequired = false, Order=6)] 
  private string m_linkType;

  public DateTime DateStart
  {
    get { return m_dateStart; }
    set { m_dateStart = value; }
  }

  public string LinkType
  {
    get { return m_linkType; }
    set { m_linkType = value; }
   }

   public DateTime DateEnd
   {
     get { return m_dateEnd; }
     set { m_dateEnd = value; }
   }
       
   public string Url
   {
     get { return m_url; }
     set { m_url = value; }
   }
        
   public long Id
   {
     get { return m_id; }
     set { m_id = value; }
   }

   public string Title
   {
     get { return m_title; }
     set { m_title = value; }
   }

  public string Description
  {
    get { return m_description; }
    set { m_description = value; }
  }
}


 

Pero al DataContract Atributo se le pueden establecer propiedades, tales como el Name y el Namespace. por defecto el nombre es el nombre del tipo en este caso es redundante, pero podria indicarle que sea expuesto con otro nombre. Lo que si tiene importancia es el namespace, Los esquemas que describen tipos complejos pertenecen generalmente a un namespace específico. Por defecto, el namespace proporcionado para ti derivará de “http://schemas.datacontract.org/2004/07”. El esquema que se generaria sin ningun aributo seria el siguiente

 

 <?xml version="1.0" encoding="utf-8" ?> 
<xs:schema elementFormDefault="qualified" 
targetNamespace="http://schemas.datacontract.org/2004/07/EventsService"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:tns="http://schemas.datacontract.org/2004/07/EventsService" 
xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/">
<xs:complexType name="LinkItem">
<xs:sequence>
  <xs:element minOccurs="0" name="DateEnd" type="xs:dateTime" /> 
  <xs:element minOccurs="0" name="DateStart" type="xs:dateTime" /> 
  <xs:element minOccurs="0" name="Description" nillable="true" type="xs:string" /> 
  <xs:element minOccurs="0" name="Id" type="xs:long" /> 
  <xs:element minOccurs="0" name="Title" nillable="true" type="xs:string" /> 
  <xs:element minOccurs="0" name="Url" nillable="true" type="xs:string" /> 
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem" /> 
</xs:schema>

 

Solamente los campos o las características marcados con el DataMemberAttribute se incluyen en la serialización (por lo tanto, en la definición del esquema). Por defecto, se serializan en orden alfabético. Para evitar dependencias cuando se cambia la definición de la clase, se puede indicar el orden del esquema con el atributo Order, ademas podemos indicar si el miembro es un elemento requerido con el atributo Requiered. Este atributo indicara al esquema que ese miembro debe aparecer en el mensaje, si dicho miembro no aparece se producira un error, rechazando el mensaje

El esquema anterior se convertiria en:

 

   <?xml version="1.0" encoding="utf-8" ?> 
<xs:schema elementFormDefault="qualified" targetNamespace=
"http://schemas.thatindigogirl.com/2005/12/LinkItems" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns=http://schemas.thatindigogirl.com/2005/12/LinkItems 
xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/">
<xs:complexType name="LinkItem">
<xs:sequence>
  <xs:element minOccurs="0" name="Id" type="xs:long" /> 
  <xs:element name="Title" nillable="true" type="xs:string" /> 
  <xs:element name="Description" nillable="true" type="xs:string" /> 
  <xs:element name="DateStart" type="xs:dateTime" /> 
  <xs:element minOccurs="0" name="DateEnd" type="xs:dateTime" /> 
  <xs:element minOccurs="0" name="Url" nillable="true" type="xs:string" /> 
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem" /> 
</xs:schema>

Podemos ver claramente las diferencias entre un esquema u otro.

 

 

Technorati tags:

Un comentario sobre “WCF DataContracts”

  1. Es recomendable usar todos los objetos dentro de mi aplicacion con DataContract o puedo tener problemas?. Los obejtos son mas pesados? que un objeto sin DataContract?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *