Está en la página 1de 57

Comenzando con

ODATA
Introducción al nuevo estándar de intercambio de datos

José Miguel Torres


Comenzando con OData
Introducción al nuevo estándar de
intercambio de datos

José Miguel Torres


ACERCA DEL AUTOR:

José Miguel Torres trabaja como Responsable de I+D+i en MRW. Cuenta con más
de 11 años de experiencia. Es autor habitual desde el año 2001 en revistas
especializadas del sector, habiendo publicado una gran variedad de artículos sobre
tecnología Microsoft. Es también autor de dos libros sobre SQL Server Compact.

Ha sido reconocido como MVP en la categoria de Device Application Development


desde el año 2008, y es miembro del grupo de usuarios de Catalunya CatDotNet y
MobileNUG Series.

Escribe regularmente tanto en su blog personal http://josemigueltorres.net como


en el portal geeks y mantiene la Web dedicada a desarrollo para dispositivos
móviles desarrolloMobile.NET así como un par de proyectos en CodePlex.

Twitter: @alegrebandolero.
COMENZANDO CON ODATA
INTRODUCCIÓN AL NUEVO ESTÁNDAR DE INTERCAMBIO DE DATOS

No está permitida la reproducción total o parcial de este libro, ni su tratamiento informático, ni la


transmisión de ninguna forma o por cualquier medio, ya sea electrónico, mecánico, por fotocopia,
por registro u otros métodos, sin el permiso previo y por escrito de los titulares del Copyright.
Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita
fotocopiar o escanear algún fragmento de esta obra.

DERECHOS RESERVADOS © 2010, respecto a la primera edición en español, por

Krasis Consulting, S. L.
www.Krasis.com
Contenido

INTRODUCCIÓN A ODATA ......................................................................................... 1


1.- Tecnologías Actuales .................................................................................................................. 1
2.- Límites de los Servicios Web ................................................................................................... 4

FUNDAMENTOS DE ODATA ....................................................................................... 7


1.- Conceptos clave de OData ....................................................................................................... 8
1.1.- Modelo de datos abstracto ........................................................................................... 8

CONSUMIENDO DATOS A TRAVÉS DE ODATA .......................................................... 15


1.- Componentes URI..................................................................................................................... 15
2.- Consultas Básicas ....................................................................................................................... 16
3.- Relación entre Entradas ........................................................................................................... 17
4.- Opciones de consulta ............................................................................................................... 19
4.1.- $orderby .......................................................................................................................... 20
4.2.- $top ................................................................................................................................... 21
4.3.- $expand ............................................................................................................................ 21
4.4.- $filter ................................................................................................................................. 23
4.5.- $inlinecount ..................................................................................................................... 23
4.6.- $select ............................................................................................................................... 24
4.7.- $skip .................................................................................................................................. 24
4.8.- $skiptoken ....................................................................................................................... 25
5.- Opciones de filtrado ................................................................................................................. 25
6.- Opciones de formato ............................................................................................................... 28

PASO A PASO: CREACIÓN DE UN SERVICIO ODATA .................................................. 29

EJEMPLOS MULTI-PLATAFORMA DE CONSUMO DE ODATA ....................................... 35


1.- Windows Phone 7 ..................................................................................................................... 36
2.- Ejemplo con WCF ..................................................................................................................... 37
3.- Ejemplo con jQuery .................................................................................................................. 40
4.- Accediendo desde Excel 2010 mediante PowerPivot ...................................................... 41
5.- SQL Azure ................................................................................................................................... 44
6.- LINQPad ...................................................................................................................................... 45

CONCLUSIONES Y RESUMEN DE ODATA .................................................................. 49


1.- Referencias utilizadas ................................................................................................................ 49
2.- Algunas referencias interesantes ........................................................................................... 50

v
¿Te interesa este libro?
Compra el libro electrónico en nuestra tienda: http://shop.campusmvp.com

- En formato PDF
- Sin DRM
- Imprimible
- Busca en el contenido

Especialistas en formación online y libros


de tecnologías Microsoft.

Síguenos y descubrirás los mejores trucos y recursos:


1
CAPÍTULO

Introducción a OData

En este manual vamos a estudiar qué es Open Data Protocol -también conocido como
OData-, la teoría en la que se basa, el porqué de su necesidad y también como
podemos generar y consumir orígenes de datos bajo dicho estándar en la práctica. El
objetivo es que puedas usar este documento como herramienta de aprendizaje, pero
también como elemento de consulta cuando necesites ver algún detalle más teórico.
Algunas partes del mismo son bastante áridas, pese a que hemos tratado de sintetizar de
la forma más comprensible posible las especificaciones del protocolo pero entendemos
que son necesarias para conseguir para entender el funcionamiento y peculiaridades de
OData. No te desanimes y al final tendrás una buena visión tanto conceptual como
práctica de este emergente estándar de intercambio de datos entre aplicaciones.

1.- TECNOLOGÍAS ACTUALES

Para entender la utilidad real que ofrece OData tratemos de imaginar un escenario
en el que tengamos el requisito de compartir un origen de datos a través de tecnología
Internet. Escenarios como en el que en muchas ocasiones nos hemos encontrado como
desarrolladores, y en el que nos han solicitado tener acceso a determinada información
de la base de datos de producción para la creación de Informes, por ejemplo datos de
ventas para el informes del Departamento Financiero. En estos escenarios podemos
exponer los datos utilizando los mecanismos de replicación y sincronización de la
mayoría de bases de datos empresariales. Sin embargo, cuando tenemos que compartir
los datos fuera de la Internet corporativa a través de Internet, o incluso a través de la
propia Intranet de la compañía (por ejemplo si el Departamento Financiero puede estar
ubicado en Madrid y los datos están en Barcelona), entonces los mecanismos de
sincronización y replicación no siempre son válidos. Además, los sistemas de
replicación y sincronización tienen un coste elevado y más si el objetivo del “futuro”
cliente no es únicamente consultar sino además modificar.

1
2 Comenzando con OData

Figura 1.- Escenario típico de replicación multi-sede

Otro escenario típico es cuando compartimos datos con terceros y además de la


distancia geográfica tenemos la barrera de la plataforma, pues los clientes de dichos
orígenes utilizan una plataforma distinta a la nuestra o sencillamente una tecnología
diferente y no interoperable. Es en este punto dónde los estándares utilizados
principalmente en los Servicios Web suelen ser la solución.
Actualmente contamos con Sitios Web y Servicios Web.
En el primer caso ejecutamos aplicaciones que en menor o mayor medida hacen uso
de una base de datos, es decir no son más que una interfaz gráfica basada en estándares
de Web como HTTP o HTML, por ejemplo, para la manipulación de datos en base al
comportamiento que especifique la aplicación o comúnmente conocida su lógica de
negocio. En realidad un Sitio Web no es una plataforma de intercambio para compartir
datos.
Los Servicios Web, por su parte, ocupan el hueco que las aplicaciones Web no
abarcan, ofreciendo comportamientos a través de métodos expuestos bajo un contrato
como lo es Web Service Definition Language (WSDL), y pese a que se han venido
utilizando como plataforma de intercambio de datos la propia naturaleza de los
Servicios Web hacen que no sea siempre la solución definitiva como veremos a
continuación.
Fijémonos en la siguiente ilustración. Pongamos un caso práctico en el que un Sitio
Web y un Servicio Web exponen, cada uno bajo sus propias peculiaridades, un
conjunto de datos de una determinada base de datos.
Introducción a OData 3

Figura 2.- Frontales de acceso a datos con servicios Web

Aparentemente y desde hace algún tiempo se ha tenido la percepción que dónde en


términos de interoperabilidad no llegaba un Sitio Web llegaba un Servicio Web. Y es
cierto que gracias a tecnologías como REST, además de SOAP, han hecho posible que
los orígenes de datos pudieran ser expuestos como Servicios Web de forma que
pudieran ser reutilizados por varias aplicaciones/plataformas cliente. De hecho, no es
extraño encontrar Servicios Web con una definición similar a la que se muestra en la
siguiente figura, en la que se exponen las operaciones relacionales básicas y que sirven
como columna vertebral de aplicaciones CRUD (siglas de Create, Read, Update y
Delete):

Figura 3.- Servicio Web para operaciones CRUD

Existen muchos de servicios de este estilo que están operativos, pero sin embargo
únicamente exponen el nivel de detalle que el desarrollador ha creído oportuno
4 Comenzando con OData

exponer. No obstante si lo que se persigue es la reutilización, casi con toda seguridad el


servicio se deberá extender para que -por ejemplo- cubra la necesidad de una nueva
aplicación que requiere la búsqueda o borrado de Cliente por determinada Provincia tal
y como se muestra en la siguiente figura:

Figura 4.- Servicio Web extendido para una necesidad particular

Ello implica la modificación del contrato del servicio (del WSDL en definitiva) y
puede tener un elevado impacto sobre las aplicaciones existentes. Como podemos
observar, este tipo de soluciones tienen algunas limitaciones. Veamos cuáles son.

2.- LÍMITES DE LOS SERVICIOS WEB

Hasta ahora, como hemos podido comprobar, cualquier modificación implica un


cambio en el Servicio Web, y este sería el mejor de los casos pues puede suceder que el
Servicio Web esté desarrollado por un tercero. De alguna forma estamos “atados” a lo
que el desarrollador ha creído conveniente exponer y no únicamente a lo “qué” ha
expuesto, sino además al “cómo” lo ha expuesto.
Pensemos por un instante la cantidad operaciones que podemos ejecutar contra las
bases de datos actuales: filtrados, ordenados, manipulación, proyecciones, funciones
sobre fechas, enteros o cadenas y así un largo etcétera. Imaginemos que de alguna
forma pudiéramos hablar un lenguaje estándar con el Servicio Web de la misma
forma que lo hacemos con nuestra base de datos, y que cuando tengamos un nuevo
requisito y necesitemos consultar los 10 clientes que más han facturado durante un
mes, pudiéramos ejecutar la consulta en el servicio y que éste nos devolviera el
resultado solicitado. Imaginemos que el formato del conjunto de datos resultante
funcionara tanto para aplicaciones Windows como para aplicaciones PHP, es decir que
hablara mediante algún estándar. De esta forma no tendríamos que ejecutar una
operación de obtención de todos los clientes en el servidor y ejecutar la operación de
Introducción a OData 5

filtrado en el lado cliente para obtener los 10 clientes que más han facturado tal y como
se debería hacer actualmente.
En definitiva Open Data Protocol es la respuesta a este nuevo escenario que ya
no es imaginario, es real y este manual pretende presentar las características aún más
trascendentes que hace indispensable conocer al menos, las bondades de esta
tecnología.
2
CAPÍTULO

Fundamentos de OData

En el capítulo anterior hablamos de un lenguaje que un Servicio Web pudiera


entender de tal forma que pudiera ejecutar operaciones relacionales y que además este
lenguaje fuera estándar. Esto es precisamente lo que Microsoft ha buscado con Open
Data Protocol de forma que se centra en tres objetivos claros:

 Crear una forma uniforme de representación de datos estructurados a través de


estándares como Atom y JSON.
 Utilizar convenciones URL uniformes para la navegación, filtrado, orden y
paginación de datos entre otros.
 Crear operaciones uniformes dirigidas por dirección y estandarización de las
acciones GET, POST, PUT y DELETE para la consulta y manipulación de
datos.

Estos tres pilares conforman Open Data Protocol (OData en adelante).


OData no es más que una estandarización, a través de la Carta de Compromiso de
Microsoft -Microsoft’s Open Specification Promise (OSP)-, de la generación y
consumo de datos vía Web. Está construido sobre un conjunto de estándares de
Internet, especialmente sobre Atom Publishing Protocol o AtomPub especificado en
RFC 5023, quién a su vez está construido sobre Atom Syndication Format (o
simplemente Atom especificado en RFC 4287).
OData permite la creación de servicio de datos basados en HTTP mediante un
modelo de datos abstracto a través del identificador uniforme de recursos (URI)
definido en RFC 2396. OData permite tanto la manipulación como la creación de datos
de cualquier origen, sean bases de datos relacionales, sistema de archivos o sistemas de
administración de contenidos (CMS), por nombrar algunos, a través de AtomPub.

7
8 Comenzando con OData

1.- CONCEPTOS CLAVE DE ODATA

Atom es una forma sencilla de exponer elementos - "feed" - de datos. El núcleo de


OData se centra en la Colecciones -Collections- de Entradas -Entries-. Cada entrada -
entry- representa un registro estructurado que representa un conjunto de Propiedades -
Properties- de datos primitivos o complejos con una o varias claves -Key-. Soporta la
relación entre entradas mediante enlaces -links-. Además OData puede exponer
funciones conocidas como Service Operations, las cuales son funciones específicas
del servicio que aceptan parámetros y devuelven estructuras de entradas.

Nota: Se expone el equivalente de los elementos utilizados en OData en inglés


para que nos familiaricemos con estos términos

1.1.- Modelo de datos abstracto

Tanto si el servicio es complejo como no, OData expone los feeds de más alto nivel
a través de AtomPub en forma de Documento. En realidad expone dos tipos de
documentos con diferentes niveles de detalle. Mientras que el Service Document
expone, como se mencionó antes, los elementos de más alto nivel, el Service Metadata
Document expone toda la descripción del Entity Data Model (EDM en adelante)
mediante la opción $metadata.

Ejemplo 1.- Service Document de http://services.odata.org/OData/OData.svc

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<service xml:base="http://services.odata.org/OData/OData.svc/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">
<workspace>
<atom:title>Default</atom:title>
<collection href="Products">
<atom:title>Products</atom:title>
</collection>
<collection href="Categories">
<atom:title>Categories</atom:title>
</collection>
<collection href="Suppliers">
<atom:title>Suppliers</atom:title>
</collection>
</workspace>
</service>

Ejemplo 2.- Service Metadata Document de


http://services.odata.org/OData/OData.svc/$metadata

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<edmx:Edmx Version="1.0"
Fundamentos de OData 9

xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
m:DataServiceVersion="2.0">
<Schema Namespace="ODataDemo"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://schemas.microsoft.com/ado/2007/05/edm">
<EntityType Name="Product">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" Nullable="true"
m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text"
m:FC_KeepInContent="false" />
<Property Name="Description" Type="Edm.String" Nullable="true"
m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text"
m:FC_KeepInContent="false" />
<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false"
/>
<Property Name="DiscontinuedDate" Type="Edm.DateTime"
Nullable="true" />
<Property Name="Rating" Type="Edm.Int32" Nullable="false" />
<Property Name="Price" Type="Edm.Decimal" Nullable="false" />
<NavigationProperty Name="Category"
Relationship="ODataDemo.Product_Category_Category_Products"
FromRole="Product_Category" ToRole="Category_Products" />
<NavigationProperty Name="Supplier"
Relationship="ODataDemo.Product_Supplier_Supplier_Products"
FromRole="Product_Supplier" ToRole="Supplier_Products" />
</EntityType>
<EntityType Name="Category">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" Nullable="true"
m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text"
m:FC_KeepInContent="true" />
<NavigationProperty Name="Products"
Relationship="ODataDemo.Product_Category_Category_Products"
FromRole="Category_Products" ToRole="Product_Category" />
</EntityType>
<EntityType Name="Supplier">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" Nullable="true"
m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text"
m:FC_KeepInContent="true" />
<Property Name="Address" Type="ODataDemo.Address" Nullable="false"
/>
<Property Name="Concurrency" Type="Edm.Int32" Nullable="false"
ConcurrencyMode="Fixed" />
<NavigationProperty Name="Products"
Relationship="ODataDemo.Product_Supplier_Supplier_Products"
FromRole="Supplier_Products" ToRole="Product_Supplier" />
10 Comenzando con OData

</EntityType>
<ComplexType Name="Address">
<Property Name="Street" Type="Edm.String" Nullable="true" />
<Property Name="City" Type="Edm.String" Nullable="true" />
<Property Name="State" Type="Edm.String" Nullable="true" />
<Property Name="ZipCode" Type="Edm.String" Nullable="true" />
<Property Name="Country" Type="Edm.String" Nullable="true" />
</ComplexType>
<Association Name="Product_Category_Category_Products">
<End Role="Product_Category" Type="ODataDemo.Product"
Multiplicity="*" />
<End Role="Category_Products" Type="ODataDemo.Category"
Multiplicity="0..1" />
</Association>
<Association Name="Product_Supplier_Supplier_Products">
<End Role="Product_Supplier" Type="ODataDemo.Product"
Multiplicity="*" />
<End Role="Supplier_Products" Type="ODataDemo.Supplier"
Multiplicity="0..1" />
</Association>
<EntityContainer Name="DemoService"
m:IsDefaultEntityContainer="true">
<EntitySet Name="Products" EntityType="ODataDemo.Product" />
<EntitySet Name="Categories" EntityType="ODataDemo.Category" />
<EntitySet Name="Suppliers" EntityType="ODataDemo.Supplier" />
<AssociationSet Name="Products_Category_Categories"
Association="ODataDemo.Product_Category_Category_Products">
<End Role="Product_Category" EntitySet="Products" />
<End Role="Category_Products" EntitySet="Categories" />
</AssociationSet>
<AssociationSet Name="Products_Supplier_Suppliers"
Association="ODataDemo.Product_Supplier_Supplier_Products">
<End Role="Product_Supplier" EntitySet="Products" />
<End Role="Supplier_Products" EntitySet="Suppliers" />
</AssociationSet>
<FunctionImport Name="GetProductsByRating" EntitySet="Products"
ReturnType="Collection(ODataDemo.Product)" m:HttpMethod="GET">
<Parameter Name="rating" Type="Edm.Int32" Mode="In" />
</FunctionImport>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>

El Service Metadata Document está descrito por EDM de forma que sea
independiente al formato en que se quiera exponer (JSON, Atom). Lo único que exige
es que se exponga a través de una interfaz HTTP. EDM está descrito en lenguaje XML
siguiendo la descripción de modelos del llamado lenguaje de definición de esquemas
conceptuales o Conceptual Schema Definition Language (CSDL en adelante).
Estas son las claves de la especificación OData ya que no comprometen la
estructura de datos a formatos propietarios sino que rigen la forma en que las
estructuras de entradas deben ser expuestas.
En la siguiente tabla podemos ver los diferentes tipos de recursos descritos en el
Entity Data Model.
Fundamentos de OData 11

Tabla 1.- Recursos OData

Recurso Descrito en el EDM por


Collection –Colección-  Conjunto de entidades
 Una propiedad de
navegación que identifica
una colección de entidades

Entry –Entrada-  Tipo de la entidad


 Nota: Los tipos de las
entidades deben forma parte
de la jerarquía de tipos.

Property of an entry –Propiedad  Propiedad de tipo Primitiva


de una entrada- o Compleja

Complex Type –Tipo Complejo-  Tipo Complejo

Link –Enlace-  Propiedad de navegación


definida en el tipo de entidad

Service Operation –Operación  Función


de Servicio-

En la Tabla 2 se refleja la relación de los tipos de datos primitivos y su expresión


literal en el EDM:

Tabla 2.- Tipos de datos primitivos

Tipo Promitivo Forma Literal Ejemplo


Null null Ejemplo 1:
Representa la null
ausencia de valor
Edm.Binary binary'[A-Fa-f0-9][A-Fa-f0-9]*' O X Ejemplo 1:
Representa un dato '[A-Fa-f0-9][A-Fa-f0-9]*' X'23AB'
binario de longitud Ejemplo 2:
fija o variable binary'23ABFF'
Edm.Boolean true | false Ejemplo 1:
Representa el true Ejemplo 2:
concepto de un valor false
lógico
12 Comenzando con OData

Edm.Byte [A-Fa-f0-9]+ Ejemplo 1: FF


Valor entero sin signo
de 8-bit
Edm.DateTime datetime'yyyy-mm- Ejemplo 1:
Representa una fecha ddThh:mm[:ss[.fffffff]]' NOTA: Los datetime'2000-12-
u hora con rangos espacios en blanco no estan permitidos. 12T12:00'
comprendidos entre Las fechas son Case Insensitive.
las 0:00:00 de la
media noche del día 1
de Enero de 1753
hasta las 23:59:59 del
9999
Edm.Decimal decimal'[0-9]+.[0-9]+' Ejemplo 1:
Representa un valor decimal'2.345'
numérico de escala y
precisión fija. Este
tipo puede describir
un valor
comprendido entre
10^255 + 1 negativo
hasta 10^255 -1
positivo
Edm.Double [0-9]+ ((.[0-9]+) | [E[+ | -][0-9]+]) Ejemplo 1:
Representa una 1E+10
número de coma Ejemplo 2:
flotante con 15 dígitos 2.029 Ejemplo 3:
de precisión con 2.0
valores comprendidos
entre ± 2.23e -308
hasta ± 1.79e +308
Edm.Single [0-9]+.[0-9]+f Ejemplo 1:
Representa un 2.0f
número de coma
flotante con 7 dígitos
de precisión que
comprende valores
entre ± 1.18e -38
hasta ± 3.40e +38
Edm.Guid guid˜dddddddd-dddd-dddd- Ejemplo 1:
Representa un valor dddddddddddd' dónde cada d representa guid'12345678-
de identificación [A-Fa-f0-9] aaaa-bbbb-
única de 16-byte (128- ccccddddffff'
bit)
Edm.Int16 [-][0-9]+ Ejemplo 1: 16
Representa un entero Ejemplo 2: -16
Fundamentos de OData 13

con signo de 16-bit


Edm.Int32 [-] [0-9]+ Ejemplo 1: 32
Representa un entero Ejemplo 2: -32
con signo de 32-bit
Edm.Int64 [-] [0-9]+L Ejemplo 1:
Representa un entero 64L Ejemplo 2: -
con signo de 64-bit 64L
Edm.SByte [-] [0-9]+ Ejemplo 1: 8
Representa un entero Ejemplo 2: -8
con signo de 8-bit
Edm.String '<cualquier UTF-8 caracter>' Nota: Ejemplo 1:
Representa una ver definición de UTF8 en [RFC3629] 'Hello OData'
cadena de longitud
fija o variable
Edm.Time time'<timeLiteral>' timeLiteral = Ejemplo 1:
Representa una hora Definido por la representación léxica de 13:20:00
del día con valores la hora en
comprendidos entre http://www.w3.org/TR/xmlschema-2
las 0:00:00.x hasta las
23:59:59.y dónde x e y
dependen de la
precisión
Edm.DateTimeOffset datetimeoffset'<dateTimeOffsetLiteral>' Ejemplo 1:
Representa una fecha dateTimeOffsetLiteral = Definido por la 2002-10-
u hora relativa a la representación léxica para datetime en 10T17:00:00Z
hora universal http://www.w3.org/TR/xmlschema-2
coordinada UCT con
valores comprendidos
entre las 0:00:00 de la
media noche del día 1
de Enero de 1753
hasta las 23:59:59 del
9999
3
CAPÍTULO

Consumiendo datos a
través de OData

Para exponer una serie de recursos definidos bajo el modelo de datos EDM, en un
servicio de datos basado en REST y siguiendo las especificaciones OData, se deben
seguir unas convenciones en lo que respecta a la URI (Uniform Resource Indetifier). El
primer paso necesario para comprender el funcionamiento de OData es conocer dichas
convenciones por elementos.

1.- COMPONENTES URI

El URI utilizado por un servicio OData consta de tres partes:

 El URI raíz del servicio

 La dirección de los recursos

 La cadena de opciones de consulta

La Figura 1 ilustra estos elementos:

Figura 1.- Componentes URI

El siguiente ejemplo representaría la consulta que nos permitiría obtener los dos
primeros Productos de la Categoria identificada a través de la clave primaria con valor
1 y ordenados por alfabéticamente por su nombre:

15
16 Comenzando con OData

Figura 2.- Ejemplo de URI con sus elementos marcados

2.- CONSULTAS BÁSICAS

Todas las consultas sobre entidades básicas, entidades agrupadas en colecciones o


propiedades de entidades, pueden ser consultadas mediante la dirección de recursos.
A continuación se detallan las descripciones de los elementos navegables:

 Collection: El nombre de la colección u operación que devuelve una colección


de entradas expuestas por el servicio.

 KeyPredicate: Un predicado que identifica el/los valores de las propiedades


de clave de una Entrada. Si la Entrada tiene una única Propiedad Clave el
predicado puede incluir únicamente el valor de la propiedad clave. Si la clave
tiene más de un valor entonces el valor debe ser asociado al nombre de la
Propiedad Clave tal y como se muestra en la siguiente figura:

Figura 3.- Estructura de predicado

 NavPropSingle: El nombre de la Propiedad de Navegación definida por una


Entrada y asociada con el segmento de dirección anterior. La Propiedad de
Navegación debe identificar una única entidad, es decir la relación es “a uno”.

 NavPropCollection: Lo mismo que el anterior pero la relación es “a varios”.

 ComplexType: El nombre de la Propiedad dinámica o declarada de una


Entrada o Tipo Complejo asociado al segmento de dirección anterior.

 Property: El nombre de la Propiedad dinámica o declarada de la Entrada o


Tipo Complejo asociado al segmento de dirección anterior.

A continuación podemos ver ejemplos de algunos casos comunes:


Consumiendo datos a través de OData 17

- Consulta de colecciones de entidades (Collections), en este caso los datos de


categorías:
http://services.odata.org/OData/OData.svc/Categories

- Consulta de una única entidad (KeyPredicate)


http://services.odata.org/OData/OData.svc/Categories(1)

- Consulta de una propiedad de una entidad (Property)


http://services.odata.org/OData/OData.svc/Categories(1)/Name

- Consulta del valor de una propiedad de una entidad (Property)


http://services.odata.org/OData/OData.svc/Categories(1)/Name/$value

3.- RELACIÓN ENTRE ENTRADAS

Por otra parte la relación entre entradas sigue la siguiente convención:

Figura 4.- Convención de relaciones entre Entradas

Por ejemplo, para navegar por una entrada cualquiera, en nuestro caso la lista de
categorías con Id igual a 0, usaremos la siguiente dirección:
http://services.odata.org/OData/OData.svc/Categories(0)

Y obtendremos el siguiente resultado en la respuesta:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<entry xml:base="http://services.odata.org/OData/OData.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/met
adata" xmlns="http://www.w3.org/2005/Atom">

<id>http://services.odata.org/OData/OData.svc/Categories(0)</id>
<title type="text">Food</title>
<updated>2010-04-23T13:22:49Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Category" href="Categories(0)" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related
18 Comenzando con OData

/Products" type="application/atom+xml;type=feed" title="Products"


href="Categories(0)/Products" />
<category term="ODataDemo.Category"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/sche
me" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">0</d:ID>
<d:Name>Food</d:Name>
</m:properties>
</content>
</entry>

Si nos fijamos la entrada tiene un elemento <link>, señalado en negrita, que


describe el tipo de relación entre la Categoría y los Productos. En el propio elemento
tenemos la dirección de referencia de los productos:

http://services.odata.org/OData/OData.svc/Categories(0)/Products

Si navegamos hacia ella obtendremos:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<feed xml:base="http://services.odata.org/OData/OData.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/met
adata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Products</title>

<id>http://services.odata.org/OData/OData.svc/Categories(0)/Produc
ts</id>
<updated>2010-04-23T13:32:45Z</updated>
<link rel="self" title="Products" href="Products" />
<entry>

<id>http://services.odata.org/OData/OData.svc/Products(0)</id>
<title type="text">Bread</title>
<summary type="text">Whole grain bread</summary>
<updated>2010-04-23T13:32:45Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Product" href="Products(0)" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related
/Category" type="application/atom+xml;type=entry" title="Category"
href="Products(0)/Category" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related
/Supplier" type="application/atom+xml;type=entry" title="Supplier"
Consumiendo datos a través de OData 19

href="Products(0)/Supplier" />
<category term="ODataDemo.Product"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/sche
me" />
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">0</d:ID>
<d:ReleaseDate m:type="Edm.DateTime">1992-01-
01T00:00:00</d:ReleaseDate>
<d:DiscontinuedDate m:type="Edm.DateTime" m:null="true"
/>
<d:Rating m:type="Edm.Int32">4</d:Rating>
<d:Price m:type="Edm.Decimal">2.5</d:Price>
</m:properties>
</content>
</entry>
</feed>

Nótese que el resultado es el Service Document de la entrada Products. Éste a su


vez tiene enlaces definidos por elementos <link> a otras entidades relacionadas, como
Supplier y, evidentemente, Category.
Para consultar las Productos que pertenecen a la categoría anterior utilizaríamos el
elemento/clave $link de la siguiente forma:

http://services.odata.org/OData/OData.svc/Categories(0)/$links/Products

Obteniendo el resultado siguiente:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>


<links
xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">

<uri>http://services.odata.org/OData/OData.svc/Products(0)</uri>
</links>

Es decir una única entrada relacionada, la correspondiente al producto con Id igual a


0.

4.- OPCIONES DE CONSULTA

Hasta ahora hemos visto algunas opciones de navegación e introducido,


indirectamente, algunos elementos de consulta como $value. Además, en el último
ejemplo, podríamos haber hecho uso de $count de la siguiente forma:

http://services.odata.org/OData/OData.svc/Categories(0)/$links/Products/$
count

Obteniendo como resultado el número de entradas, en nuestro caso 1.


20 Comenzando con OData

Sin embargo aún podemos sacar mucho más provecho a través de las opciones de
ordenado o de función como por ejemplo $top.
En la siguiente figura se observa el resultado de una consulta realizada sobre un
servicio hospedado en localhost, en la que se muestran los 3 primeros clientes
ordenados por el campo FirstName de manera descendente.

Figura 5.- Resultado de consulta que devuelve los tres primeros elementos

Además de las opciones de ordenación y top podemos utilizar las siguientes:

4.1.- $orderby

La opción $orderby devuelve una consulta ordenada por la/s propiedad/es


indicada/s.
Algunos ejemplos de su uso son:

- Retorna una Colección de Entradas ordenadas por la propiedad FirstName


http://localhost:12560/AdventureWorksService.svc/Customer?$orderby=Fi
rstName

- Lo mismo pero en forma ascendente


Consumiendo datos a través de OData 21

http://localhost:12560/AdventureWorksService.svc/Customer?$orderby=Fi
rstName asc

- En el siguiente ejemplo se ordena primero por el campo OrderDate de la


Entrada SalesOrderHeader y después por el campo FirstName de la Entrada
enlazada Customer.
http://localhost:12560/AdventureWorksService.svc/SalesOrderHeader?$orderb
y=OrderDate,Customer/FirstName

4.2.- $top

La opción $top devuelve las n primeras entradas indicadas por el valor $top=n.
El siguiente ejemplo devuelve los 5 productos con coste estándar más alto.

http://localhost:12560/AdventureWorksService.svc/Product?$orderby=Standar
dCost&$top=5

4.3.- $expand

Esta opción es especialmente útil para mostrar las relaciones de más de una Entrada.
Es decir, si por ejemplo quisiéramos mostrar una Entrada Customer y su Entrada
relacionada representada por CustomerAddress podríamos hacerlo mediante dos
consultas ejecutadas consecutivamente, o bien podríamos hacerlo en una sola mediante
la opción $expand.
El siguiente ejemplo ilustra la obtención del primer Customer ($top=1) con
CustomerAddress.

http://localhost:12560/AdventureWorksService.svc/Customer?$expand=Custome
rAddress&$top=1
Resultado:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<feed
xml:base="http://localhost:12560/AdventureWorksService.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/met
adata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Customer</title>

<id>http://localhost:12560/AdventureWorksService.svc/Customer</id>
<updated>2010-04-26T08:03:08Z</updated>
<link rel="self" title="Customer" href="Customer" />
<entry>

<id>http://localhost:12560/AdventureWorksService.svc/Customer(1)</
id>
<title type="text"></title>
<updated>2010-04-26T08:03:08Z</updated>
22 Comenzando con OData

<author>
<name />
</author>
<link rel="edit" title="Customer" href="Customer(1)" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related
/CustomerAddress" type="application/atom+xml;type=feed"
title="CustomerAddress" href="Customer(1)/CustomerAddress">
<m:inline>
<feed>
<title type="text">CustomerAddress</title>

<id>http://localhost:12560/AdventureWorksService.svc/Customer(1)/C
ustomerAddress</id>
<updated>2010-04-26T08:03:08Z</updated>
<author>
<name />
</author>
<link rel="self" title="CustomerAddress"
href="Customer(1)/CustomerAddress" />
</feed>
</m:inline>
</link>
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related
/SalesOrderHeader" type="application/atom+xml;type=feed"
title="SalesOrderHeader" href="Customer(1)/SalesOrderHeader" />
<category term="AdventureWorksLT2008Model.Customer"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/sche
me" />
<content type="application/xml">
<m:properties>
<d:CustomerID m:type="Edm.Int32">1</d:CustomerID>
<d:NameStyle m:type="Edm.Boolean">false</d:NameStyle>
<d:Title>Mr.</d:Title>
<d:FirstName>Orlando</d:FirstName>
<d:MiddleName>N.</d:MiddleName>
<d:LastName>Gee</d:LastName>
<d:Suffix m:null="true" />
<d:CompanyName>A Bike Store</d:CompanyName>
<d:SalesPerson>adventure-works\pamela0</d:SalesPerson>
<d:EmailAddress>orlando0@adventure-
works.com</d:EmailAddress>
<d:Phone>245-555-0173</d:Phone>

<d:PasswordHash>L/Rlwxzp4w7RWmEgXX+/A7cXaePEPcp+KwQhl2fJL7w=</d:Pa
sswordHash>
<d:PasswordSalt>1KjXYs4=</d:PasswordSalt>
<d:rowguid m:type="Edm.Guid">3f5ae95e-b87d-4aed-95b4-
Consumiendo datos a través de OData 23

c3797afcb74f</d:rowguid>
<d:ModifiedDate m:type="Edm.DateTime">2001-08-
01T00:00:00</d:ModifiedDate>
</m:properties>
</content>
</entry>
</feed>

4.4.- $filter

Filtra las entradas por una expresión lógica, aritmética o de agrupación. Veremos
más detalles sobre las opciones de este filtro en la siguiente sección.

4.5.- $inlinecount

Retorna el número de Entradas encontradas en el documento si indicamos el valor


$inlinecount=allpages. El valor por defecto es $inlinecount=none.
Por ejemplo, la siguiente URI retornará todos los productos cuyo coste estándar sea
superior a 2000, e indicará la cantidad de entradas que satisfacen el filtro mediante la
una marca <count> en el resultado:

http://localhost:12560/AdventureWorksService.svc/Product?$filter=Standard
Cost gt 2000&$inlinecount=allpages

El resultado es el siguiente:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<feed
xml:base="http://localhost:12560/AdventureWorksService.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/met
adata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Product</title>

<id>http://localhost:12560/AdventureWorksService.svc/Product</id>
<updated>2010-04-26T10:15:30Z</updated>
<link rel="self" title="Product" href="Product" />
<m:count>5</m:count>
<entry>

El siguiente ejemplo, y esto es importante, pese a la existencia de la opción $top=2


retornará también 5 entradas en el elemento <count>, ya que son las que se han
procesado en el servicio antes de devolver los datos:
24 Comenzando con OData

http://localhost:12560/AdventureWorksService.svc/Product?$filter=Standard
Cost gt 2000&$inlinecount=allpages&$top=2

4.6.- $select

Esta opción identifica el subconjunto de propiedades de un origen OData a


devolver. $select únicamente está soportada en la versión 2.0 y superior.
En el siguiente ejemplo se devolverán únicamente las Propiedades especificadas
como valor en $select.

http://localhost:12560/AdventureWorksService.svc/Product(680)?$select=Nam
e,Color,StandardCost

Y su resultado será:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<entry xml:base="http://localhost:12560/AdventureWorksService.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://www.w3.org/2005/Atom">
<id>http://localhost:12560/AdventureWorksService.svc/Product(680)</id>
<title type="text"></title>
<updated>2010-04-26T10:03:31Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Product" href="Product(680)" />
<category term="AdventureWorksLT2008Model.Product"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Name>HL Road Frame - Black, 58</d:Name>
<d:Color>Black</d:Color>
<d:StandardCost m:type="Edm.Decimal">1059.3100</d:StandardCost>
</m:properties>
</content>
</entry>

4.7.- $skip

Esta opción obvia las n primeras entradas indicadas por el valor $skip=n.
El siguiente URI devuelve los 5 productos con coste estándar más alto, obviando
los dos primeros.

http://localhost:12560/AdventureWorksService.svc/Product?$orderby=Standar
dCost&$top=5&$skip=2
Consumiendo datos a través de OData 25

4.8.- $skiptoken

Esta opción es especialmente útil junto a $orderby, ya que trabaja como un cursor
indicando a partir de qué valor del elemento o propiedad o de la clave debe retornar los
resultados. Es decir, supongamos el siguiente ejemplo:

http://localhost:12560/AdventureWorksService.svc/Customer?$orderby=FirstN
ame&$skiptoken='Yuping'

El resultado será las Entradas ordenada por FirstName desde el cliente llamado
Yuping hasta el final. En este caso se obvian todos los clientes cuyo nombre –
FirstName- se alfabéticamente anterior al valor del $skiptoken.

5.- OPCIONES DE FILTRADO

Anteriormente hablábamos acerca de los operadores de la opción $filter y es que


existen concretamente tres categorías de operadores: lógicos, aritméticos y de
agrupamiento.
A continuación se muestra una tabla con todos los operadores agrupados por
categoría así como una descripción y un ejemplo de uso.
Tabla 3.- Operadores de filtro

Operador Descripción Ejemplo


Operadores lógicos
Eq Igual /Suppliers?$filter=Address/
City eq 'Redmond'
Ne No igual /Suppliers?$filter=Address/
City ne 'London'
Gt Mayor que /Products?$filter=Price gt 20
Ge Mayor o igual /Products?$filter=Price ge
que 10
Lt Menor que /Products?$filter=Price lt 20
Le Menor o igual /Products?$filter=Price le
que 100
And Operador /Products?$filter=Price le
lógico Y 200 and Price gt 3.5
Or Operador /Products?$filter=Price le
lógico O 3.5 or Price gt 200
Not Operador /Products?$filter=not
lógico negación endswith(Description,'milk')
NI
26 Comenzando con OData

Operadores aritméticos
Add Suma /Products?$filter=Price add
5 gt 10
Sub Resta /Products?$filter=Price sub
5 gt 10
Mul Multiplicación /Products?$filter=Price mul
2 gt 2000
Div División /Products?$filter=Price div 2
gt 4
Mod Módulo /Products?$filter=Price mod
2 eq 0
Operadores de agrupamiento
() Agrupación /Products?$filter=(Price sub
5) gt 10

Además existen una serie de funciones para los operadores o funciones, específicos
para el tratamiento de:

 Cadenas
 Fechas
 Expresiones matemáticas
 De tipo

Las cuales podemos ver en las siguientes tablas, con un ejemplo asociado a cada uno de
ellos:
Tabla 4.- Funciones de cadena

Función Ejemplo
bool substringof(string http://services.odata.org/Northwind/Northwind.svc
p0, string p1) /Customers?$filter=substringof('Alfreds',
CompanyName) eq true
bool endswith(string http://services.odata.org/Northwind/Northwind.svc
p0, string p1) /Customers?$filter=endswith(CompanyName,
'Futterkiste') eq true
bool startswith(string http://services.odata.org/Northwind/Northwind.svc
p0, string p1) /Customers?$filter=startswith(CompanyName,
'Alfr') eq true
int length(string p0) http://services.odata.org/Northwind/Northwind.svc
/Customers?$filter=length(CompanyName) eq 19
int indexof(string p0, http://services.odata.org/Northwind/Northwind.svc
string p1) /Customers?$filter=indexof(CompanyName,
'lfreds') eq 1
Consumiendo datos a través de OData 27

string replace(string p0, http://services.odata.org/Northwind/Northwind.svc


string find, string /Customers?$filter=replace(CompanyName, ' ', '')
replace) eq 'AlfredsFutterkiste'
string substring(string http://services.odata.org/Northwind/Northwind.svc
p0, int pos) /Customers?$filter=substring(CompanyName, 1)
eq 'lfreds Futterkiste'
string substring(string http://services.odata.org/Northwind/Northwind.svc
p0, int pos, int length) /Customers?$filter=substring(CompanyName, 1, 2)
eq 'lf'
string tolower(string http://services.odata.org/Northwind/Northwind.svc
p0) /Customers?$filter=tolower(CompanyName) eq
'alfreds futterkiste'
string toupper(string http://services.odata.org/Northwind/Northwind.svc
p0) /Customers?$filter=toupper(CompanyName) eq
'ALFREDS FUTTERKISTE'
string trim(string p0) http://services.odata.org/Northwind/Northwind.svc
/Customers?$filter=trim(CompanyName) eq
'Alfreds Futterkiste'
string concat(string p0, http://services.odata.org/Northwind/Northwind.svc
string p1) /Customers?$filter=concat(concat(City, ', '),
Country) eq 'Berlin, Germany'

Tabla 5.- Funciones de fecha

Función Ejemplo
int day(DateTime p0) http://services.odata.org/Northwind/Northwind.svc
/Employees?$filter=day(BirthDate) eq 8
int hour(DateTime p0) http://services.odata.org/Northwind/Northwind.svc
/Employees?$filter=hour(BirthDate) eq 0
int minute(DateTime http://services.odata.org/Northwind/Northwind.svc
p0) /Employees?$filter=minute(BirthDate) eq 0
int month(DateTime http://services.odata.org/Northwind/Northwind.svc
p0) /Employees?$filter=month(BirthDate) eq 12
int second(DateTime http://services.odata.org/Northwind/Northwind.svc
p0) /Employees?$filter=second(BirthDate) eq 0
int year(DateTime p0) http://services.odata.org/Northwind/Northwind.svc
/Employees?$filter=year(BirthDate) eq 1948

Tabla 6.- Funciones matemáticas

Función Ejemplo
28 Comenzando con OData

double round(double http://services.odata.org/Northwind/Northwind.svc


p0) /Orders?$filter=round(Freight) eq 32
decimal round(decimal http://services.odata.org/Northwind/Northwind.svc
p0) /Orders?$filter=round(Freight) eq 32
double floor(double p0) http://services.odata.org/Northwind/Northwind.svc
/Orders?$filter=filter=round(Freight) eq 32
decimal floor(decimal http://services.odata.org/Northwind/Northwind.svc
p0) /Orders?$filter=floor(Freight) eq 32
double ceiling(double http://services.odata.org/Northwind/Northwind.svc
p0) /Orders?$filter=ceiling(Freight) eq 33
decimal http://services.odata.org/Northwind/Northwind.svc
ceiling(decimal p0) /Orders?$filter=floor(Freight) eq 33

Tabla 7.- Funciones de tipo

Función Ejemplo
bool IsOf(type p0) http://services.odata.org/Northwind/Northwind.svc
/Orders?$filter=isof('NorthwindModel.Order')
bool IsOf(expresión p0, http://services.odata.org/Northwind/Northwind.svc
type p1) /Orders?$filter=isof(ShipCountry, 'Edm.String')

6.- OPCIONES DE FORMATO

Otra de las características que nos permiten las opciones de consulta es la de


obtener el resultado en formato Atom (por defecto), en formato JSON o en formato
XML.
Ejemplos:

http://services.odata.org/OData/OData.svc/Products?$format=atom

http://services.odata.org/OData/OData.svc/Products?$format=json

http://services.odata.org/OData/OData.svc/Products?$format=xml

Nota: Destacar que en el caso que expongamos nosotros mismos un servicio


de datos deberemos interceptar los mensajes y cambiar la cabecera de la respuesta
a “application/json”. Para más información ver el siguiente enlace
http://code.msdn.microsoft.com/DataServicesJSONP.
4
CAPÍTULO

Paso a paso: creación de


un servicio OData

Existen varios orígenes de datos públicos expuestos por diversas entidades a la


comunidad, tales como:

 OData Test Service


 Read-Only Northwind Service
 Vancouver Street Parking
 Open Government Data Initiative
 The City of Edmonton Open Data Catalogue
 MIX 2010
 Netflix
 Codename “Dallas”

Así como varios entornos de desarrollo que soportan la creación de orígenes OData
como:

 Microsoft .NET Framework 3.5 a través de WCF Data Services Framework


 Microsoft .NET Framework 4.0 a través de WCF Data Services Framework
 Sharepoint 2010 que expone toda la información a través de OData
 IBM WebSphere
 SQL Azure
 Windows Azure Storage
 SQL Server Reporting Services

Lo que vamos a ver es un ejemplo de creación de un servicio OData con Microsoft


Visual Studio .NET 2010 y .NET Framework 4.0, con la base de datos de ejemplo
AdventureWorksLT2008.

29
30 Comenzando con OData

Para ello basta con crear un nuevo proyecto ASP.NET Web Application para
hospedar el servicio. Dado que vamos a representar íntegramente la base de datos
AdventureWorksLT2008 lo primero que vamos a hacer es crear un modelo de entidades
a través de ADO.NET Entity Framework, añadiendo el elemento ADO.NET Entity
Data Model:

Figura 1.- Creación de un modelo de datos con Entity Framework

Una vez seleccionada la plantilla e indicado el nombre generaremos el modelo a


partir de una base de datos.

Figura 2.- Asistente para generación del modelo a partir de una base de datos
Paso a paso: creación de un servicio OData 31

Creamos y seleccionamos la cadena de conexión a AdventureWorksLT2008 y


almacenamos la cadena de conexión en el archivo Web.config.

Figura 3.- Paso para definir la cadena de conexión

Nótese que la cadena de conexión a la entidad viene determinada por la definición


del CSDL:

metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;p
rovider=System.Data.SqlClient;provider connection string="Data
Source=LATITUDE-E6400;Initial Catalog=AdventureWorksLT2008;Integrated
Security=True"

En el siguiente paso seleccionamos todas la tablas de la base de datos:


32 Comenzando con OData

Figura 4.- Selección de tablas

Y finalmente tendremos el modelo de entidades agregado a nuestro proyecto.

Figura 5.- El modelo de datos que vamos a exponer


Paso a paso: creación de un servicio OData 33

Ahora hay que exponer el modelo a un servicio y para ello añadimos un nuevo
elemento WCF Data Service:

Figura 6.- Insertamos un nuevo servicio de datos WCF

Por último configuramos el servicio para que haga uso del modelo de entidades
generado anteriormente:

public class AdventureWorksService :


DataService<AdventureWorksLT2008Entities>
{
public static void InitializeService(DataServiceConfiguration
config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.SetServiceOperationAccessRule("*",
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
}
}

Y ejecutamos el servicio en el explorador:


34 Comenzando con OData

Figura 7.- El servicio “puro” funcionando en el navegador

A continuación veremos cómo consumir este servicio desde diversos clientes.


5
CAPÍTULO

Ejemplos multi-
plataforma de consumo
de OData
De la misma forma que tenemos herramientas para la generación de orígenes OData,
disponemos de múltiples herramientas de desarrollo a nuestro alcance para la
manipulación en el lado cliente de esos datos, como por ejemplo:

 Cualquier explorador Web.


 Microsoft .NET Framework 3.51 y 4.0
 Silverlight 3 y 4
 Windows Phone 7
 Java
 JavaScript
 PHP
 AJAX
 Excel 2010 PowerPivot
 LINQPad

Nota: Podemos encontrar el código fuente de las librerías clientes para OData
de Silverlight 3.0 y .NET Framework 3.5 SP1 en el sitio
http://odata.codeplex.com, bajo licencia Apache 2.0.

35
36 Comenzando con OData

Figura 1.- Listado de herramientas disponibles en OData.org

A continuación veremos algunos ejemplos de las librerías cliente que están


actualmente disponibles para OData.

1.- WINDOWS PHONE 7

OData es la plataforma de servicios de datos para las aplicaciones Windows Phone


7. Podrá encontrar más información en MobilNUG Series.

Figura 2.- Ejemplo de consumo de OData desde Windows Phone 7


Ejemplos multi-plataforma de consumo de OData 37

2.- EJEMPLO CON WCF

Para crear el cliente o proxy al servicio de datos podemos utilizar el propio Visual
Studio .NET 2008/2010:

Figura 3.- Diálogo de añadir referencia a servicio en Visual Studio

O mediante la herramienta de comandos datasvcutil.exe:

Figura 4.- Herramienta de generación de proxies manual, datasvcutil.exe


38 Comenzando con OData

En ambos casos obtendremos un conjunto de clases que definen tanto el contexto


como las entradas que describen las entidades.
En el ejemplo mostraremos los resultados en un simple DataGrid por lo que la
interfaz no tendrá más que un botón para ejecutar la llamada al servicio.

Figura 5.- Formulario simple con una rejilla y un botón WPF

La lógica que aplicaremos es la de llamar y obtener todos los productos bajo una
condición y ordenados por un campo, tal y como se muestra en el cuerpo del evento del
botón en el siguiente fragmento, que se corresponde con el código fuente completo de
la ventana WPF:

public partial class MainWindow : Window


{
private readonly AdventureWorksLT2008Entities m;

public MainWindow()
{
InitializeComponent();

m= new AdventureWorksLT2008Entities(
new
Uri("http://localhost:12560/AdventureWorksService.svc"));
}

private void button1_Click(object sender, RoutedEventArgs e)


{
dataGrid1.AutoGenerateColumns = true;

var query = (from pro in m.Product


where pro.ListPrice > 100
orderby pro.StandardCost
select pro) as DataServiceQuery<Product>;
Ejemplos multi-plataforma de consumo de OData 39

dataGrid1.ItemsSource = query.ToList();
}

Nótese que si agregamos un punto de interrupción en tiempo de depuración, el


objeto query contendrá la convención URI equivalente a las operaciones de filtrado y
ordenación vistas anteriormente.

Figura 6.- La URI OData resultante de la consulta

La aplicación tras la ejecución tiene el siguiente aspecto:

Figura 7.- Aspecto de la aplicación WPF


40 Comenzando con OData

3.- EJEMPLO CON JQUERY

Otro ejemplo demostrativo es la consulta de este tipo de servicios mediante


JavaScript, más concretamente usando la biblioteca jQuery.
En el siguiente código se realiza una llamada al servicio de datos obteniendo
únicamente los dos primeros (sentencia $top) y se realiza su representación básica en el
explorador.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>OData con JQuery</title>
<script src="/Scripts/jquery-1.3.2.js" type="text/javascript">
</script>
</head>
<body>
<script type="text/javascript">
$(function cargando() {
$("#foo").text("cargando...");
var url =
"http://localhost:12560/AdventureWorksService.svc/Product?$top=2";
$.getJSON(url, function (result) {
$.each(result.d, function (i, item) {
$('#products').append('<div id=H' + i + '><p> ---
> Product info</p></div>');
$('#H' + i).append('<p> ProductID: ' +
item.ProductID + '</p>');
$('#H' + i).append('<p> Name: ' + item.Name +
'</p>');
$('#H' + i).append('<p> ProdNumber: ' +
item.ProductNumber + '</p>');
});
});
});
</script>
<p>Ejemplo OData</p>
<div id="products">
</div>
</body>
</html>

El resultado de ejecutar el código anterior en una página HTML es el siguiente:


Ejemplos multi-plataforma de consumo de OData 41

Figura 8.- Ejemplo sencillo con jQuery

4.- ACCEDIENDO DESDE EXCEL 2010 MEDIANTE


POWERPIVOT

Otro de los clientes disponibles para consumir OData es Microsoft Excel 2010
utilizando su extensión gratuita PowerPivot. Lo único que necesitamos es
descargárnosla desde www.powerpivot.com e instalarla.
Para configurar un origen de datos OData basta con una ventana PowerPivot tal y
como se muestra a continuación:

Figura 9.- Abrir nueva ventana de PowerPivot

E indicamos el origen y el URI del servicio de datos:


42 Comenzando con OData

Figura 10.- Enlazar desde PowerPivot con el servicio de datos OData

A continuación seleccionamos las Entradas que queremos tratar con PowerPivot:


Ejemplos multi-plataforma de consumo de OData 43

Figura 11.- Selección de tablas desde el origen OData

Y comenzará la importación de datos:

Figura 12.- Importación de datos en PowerPivot


44 Comenzando con OData

Finalmente tendremos todos los datos de las Entradas repartidas en Hojas del libro
PowerPivot.

Figura 13.- Datos importados en PowerPivot y listos para analizar

5.- SQL AZURE

Una de las novedades que presentó Microsoft en el pasado MIX2010 que tuvo lugar
en Las Vegas fue la compatibilidad de cualquier base de datos SQL Azure para ser
expuesta como OData. Es decir que si hospedamos una base de datos SQL Azure
tendremos la opción de exponerla como servicio OData, y sin necesidad de tener que
crear el servicio, algo que si hacemos con otros modelo de datos y que hemos visto
anteriormente.
Lo único que debemos hacer es visitar OData Service Portal y seguir el asistente,
indicando el servidor y usuario de administración. Posteriormente seleccionamos la
base de datos que tenemos expuesta en Azure y habilitamos OData mediante la opción
Enable OData.
En ese momento se generará un EndPoint para el Servicio de Datos y podremos
seleccionar/crear los usuarios que tendrán permisos de acceso al EndPoint.
Ejemplos multi-plataforma de consumo de OData 45

Figura 14.- Configuración de un origen OData para SQL Azure

6.- LINQPAD
Otro cliente disponible para trabajar con OData es LINQPad, versión 4. Para
empezar a consumir datos de un servicio OData basta con configurar la conexión
siguiendo los pasos explicados a continuación.
En primer lugar añadimos una nueva conexión y seleccionamos WCF Data Service
para establecer el contexto del origen:
46 Comenzando con OData

Figura 15.- Definición del contexto de origen

Indicamos la URI del servicio e indicamos que se trata de un Servicio de Datos.


Configuramos el proxy a propia elección:

Figura 16.- Configuración del proxy

Y finalmente ejecutamos las consultas LINQ que queramos sobre dicho origen de
datos:
Ejemplos multi-plataforma de consumo de OData 47

Figura 17.- Consultas directas contra OData desde LINQPad


6
CAPÍTULO

Conclusiones y resumen
de OData

OData es sin duda una fuerte apuesta por parte de Microsoft para la manipulación
de datos a través de operaciones CRUD tipadas, construido sobre estándares de
Internet. Su futuro está en mano de los fabricantes/empresas, así como de la comunidad
que quiera adoptarlo bajo la promesa de código abierto –OSS (Open Source Software)-.
En este manual le hemos tratado de brindar una introducción suficiente como para dar
los primeros pasos en esta tecnología, con los conceptos teóricos suficientes, así como
con algunos ejemplos prácticos de uso de los que partir.
OData le resultará de gran utilidad en multitud de escenarios prácticos dentro de las
empresas y en arquitecturas distribuidas y para Internet.

1.- REFERENCIAS UTILIZADAS

Las tablas de referencia y algunas imágenes mostradas en este artículo han sido
extraídas de http://www.odata.org. En algunos casos se ha optado por la traducción
del contenido de algunas tablas mientras que en otros se ha optado por dejar los valores
en inglés originales para no crear confusiones y facilitar al lector la compresión de
términos utilizados por OData.

Las demás referencias utilizadas han sido:

· Open Data Protocol Documentation:


http://www.odata.org/developers/protocols

· Open Data Protocol by example de Chris Sells


http://msdn.microsoft.com/en-us/library/ff478141.aspx

49
50 Comenzando con OData

2.- ALGUNAS REFERENCIAS INTERESANTES

A continuación se ofrecen algunos enlaces adicionales que le permitirán profundizar


en el uso de OData desde distintos entornos y lenguajes de programación:

· Creating an OData API for StackOverflow including XML and JSON in 30


minutes, por Scott Hanselman.

· OData interoperability with .NET, Java, PHP, iPhone and more, en el blog de
interoperabilidad de Microsoft.

· Producing and consuming OData feeds: An end-to-end example, por Jon Udell

· Retrieving Data with the OData SDK for PHP, por Brian Swan

· Every SharePoint 2010 server is a Data Services server, por Pablo Castro

· OData and Ruby, por K. Scott Allen

También puede echarle un vistazo a la interesante herramienta Silverlight OData


Explorer, que permite examinar fuentes de datos OData directamente desde el
navegador.
¿Te interesa este libro?
Compra el libro electrónico en nuestra tienda: http://shop.campusmvp.com

- En formato PDF
- Sin DRM
- Imprimible
- Busca en el contenido

Especialistas en formación online y libros


de tecnologías Microsoft.

Síguenos y descubrirás los mejores trucos y recursos: