Você está na página 1de 128

WCF Data Service

WCF Data Services


WCF Data Services (anteriormente conocido como "ADO.NET Data Services") es un componente de .NET
Framework que permite crear servicios que utilizan Open Data Protocol (OData) para exponer y utilizar
datos a travs de web o de una intranet utilizando la semntica de transferencia de estado de
representacin (REST). OData expone los datos como recursos direccionables a travs de identificadores
uniformes de recursos (URI). Para tener acceso a los datos y cambiarlos se utilizan los verbos HTTP estndar
GET, PUT, POST y DELETE. OData usa las convenciones de entidad-relacin de Entity Data Model para
exponer los recursos como conjuntos de entidades que estn relacionadas por medio de asociaciones.
WCF Data Services usa el protocolo de OData para direccionar y actualizar los recursos. De esta manera,
puede tener acceso a estos servicios desde cualquier cliente que admita OData . OData permite solicitar
datos a los recursos y escribir en ellos mediante formatos de transferencia conocidos: JavaScript Object
Notation (JSON), un formato de intercambio de datos basado en texto muy usado en la aplicacin AJAX, y
Atom, conjunto de estndares para intercambiar y actualizar datos como XML.
WCF Data Services puede exponer datos procedentes de varios orgenes como fuentes de OData . Las
herramientas de Visual Studio facilitan la creacin de un servicio basado en OData mediante el uso de un
modelo de datos de ADO.NET Entity Framework. Tambin puede crear fuentes de OData basadas en clases
de Common Language Runtime (CLR) e incluso en datos enlazados en tiempo de ejecucin o datos sin tipo.
WCF Data Services tambin incluye dos conjuntos de bibliotecas de cliente, uno para las aplicaciones cliente
de .NET Framework generales y otro especficamente para las aplicaciones basadas en Silverlight. Estas
bibliotecas de cliente proporcionan un modelo de programacin basado en objetos cuando se tiene acceso
a una fuente de OData desde entornos como .NET Framework y Silverlight.

1. Novedades en WCF Data Services


En esta versin de WCF Data Services se admite la siguiente funcionalidad nueva de la versin 2.0 de Open
Data Protocol (OData) :
Contar las entidades de un conjunto de entidades
Un nuevo segmento de ruta de acceso $count le permite recibir solo el nmero total de recursos
devueltos por un URI. Una nueva opcin de consulta $inlinecount le permite recibir el mismo
nmero total de recursos junto con sus datos en una sola respuesta.
La biblioteca cliente de .NET Framework ahora permite acceder a esta informacin de nmero de
fila en una respuesta de la consulta de la aplicacin.
Proyecciones de consultas
Los resultados de la consulta ya se pueden modificar para incluir solo un subconjunto de
propiedades mediante el uso de la nueva opcin de consulta $select.
La biblioteca cliente de .NET Framework ahora admite proyecciones mediante el uso de la clusula
select (Select en Visual Basic) en una consulta LINQ.
La siguiente funcionalidad la proporciona la versin de WCF Data Services de .NET Framework 4:
Paginacin controlada por servidor
Un servicio de datos ya se puede configurar para devolver los recursos solicitados como conjunto
de respuestas paginadas.
La biblioteca cliente de .NET Framework ahora permite administrar respuestas paginadas.
Enlace de datos
Una nueva clase DataServiceCollection proporciona enlace simplificado de los datos del servicio de
datos a los controles de Windows Presentation Foundation (WPF). Esta clase hereda de la clase
ObservableCollection para actualizar automticamente los datos enlazados cuando se efectan
cambios en los datos de los controles enlazados.
Transmitir en secuencias recursos binarios
Una entidad se puede definir como entrada de vnculo multimedia, con un vnculo a un recurso
multimedia asociado. De esta forma, puede recuperar y guardar datos de objetos binarios grandes
independientemente de la entidad a la que pertenezcan. Puede crear un servicio de datos que
devuelva datos de propiedad binarios como flujo en vez de cargar primero la entidad completa,

MCT: Luis Dueas

Pag 1 de 128

WCF Data Service


incluidos los datos binarios, en la memoria. Para ello, implemente la interfaz
IDataServiceStreamProvider.
La biblioteca cliente de .NET Framework ahora permite obtener y establecer propiedades binarias
como flujo de datos.
Personalizacin de fuentes
WCF Data Services permite personalizar las fuentes devueltas por el servicio de datos mediante la
definicin de una asignacin de entidad-propiedad alternativa de una carga Atom.
Proveedores de servicios de datos personalizados
Mediante la implementacin de un conjunto de nuevas interfaces de proveedor de servicio de
datos, puede usar diversos tipos de datos con un servicio de datos, aunque cambie el modelo de
datos durante la ejecucin.

2. Informacin general acerca de WCF Data Services


WCF Data Services permite la creacin y la utilizacin de servicios de datos para web o para una intranet
mediante Open Data Protocol (OData) . OData permite exponer datos como recursos direccionables a travs
de identificadores uniformes de recursos (URI). De esta forma, puede acceder y cambiar datos mediante el
uso de la semntica de transferencia de estado de representacin (REST), especficamente los verbos HTTP
estndar de GET, PUT, POST y DELETE. En este tema se proporciona informacin general sobre los modelos
y los procedimientos definidos por OData y tambin las funciones proporcionadas por WCF Data Services
para aprovechar las ventajas de OData en aplicaciones basadas en .NET Framework.

Direccionamiento de datos como recursos


OData expone los datos como recursos direccionables a travs de identificadores uniformes de recursos
(URI). Las rutas de acceso de los recursos se construyen segn las convenciones del modelo entidadrelacin de Entity Data Model. En este modelo, las entidades representan unidades operacionales de datos
en un dominio de aplicacin, como clientes, pedidos, elementos y productos.
En OData , los recursos de entidades se direccionan como conjunto de entidades que contiene instancias de
tipos
de
entidad.
Por
ejemplo,
el
URI

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/ Orders devuelve todos los


pedidos del servicio de datos Northwind relacionados con el cliente con un valor CustomerID de ALFKI.
Las expresiones de consulta permiten realizar operaciones de consulta tradicionales en los recursos, como
filtrarlos, ordenarlos y paginarlos. Por ejemplo, el URI http://services.odata.org/Northwind/Northwind.svc/

Customers('ALFKI')/Orders?$filter=Freight gt 50 filtra los recursos para devolver solo los pedidos cuyo
costo de flete sea mayor que 50 dlares.

Interoperabilidad en el acceso a los datos


OData se basa en los protocolos estndar de Internet para lograr que los servicios de datos puedan
interoperar con aplicaciones que no usan .NET Framework. Dado que es posible usar los URI estndar para
direccionar los datos, una aplicacin puede obtener acceso a los datos y modificarlos usando la semntica
de la Transferencia de estado de representacin (REST), especficamente los verbos HTTP estndar GET, PUT,
POST y DELETE. Esto le permite tener acceso a estos servicios desde cualquier cliente que pueda analizar y
tener acceso a los datos que se transmiten mediante los protocolos HTTP estndar.
OData define un conjunto de extensiones del protocolo de publicacin Atom (AtomPub). Es compatible con
solicitudes y respuestas HTTP en ms de un formato de datos para albergar distintas aplicaciones y
plataformas cliente. Una fuente OData puede representar los datos en formato Atom, JavaScript Object
Notation (JSON) y como XML sin formato. Aunque Atom es el formato predeterminado, el formato de la
fuente se especifica en el encabezado de la solicitud HTTP.
Cuando se publican los datos como fuente de OData , WCF Data Services se basa en otros servicios de
Internet existentes para operaciones como el almacenamiento en memoria cach y la autenticacin. Para
ello, WCF Data Services se integra con los servicios y aplicaciones de hospedaje existentes, como ASP.NET,
Windows Communication Foundation (WCF) e Internet Information Services (IIS).

Independencia de almacenamiento
MCT: Luis Dueas

Pag 2 de 128

WCF Data Service


Aunque los recursos se direccionan basndose en un modelo entidad-relacin, WCF Data Services expone
fuentes de OData sin tener en cuenta el origen de datos subyacente. Despus de que WCF Data Services
acepte una solicitud HTTP para un recurso identificado mediante un URI, se deserializa la solicitud y se pasa
una representacin de la misma a un proveedor de WCF Data Services . Este proveedor traduce la solicitud
en un formato especfico del origen de datos y la ejecuta en el origen de datos subyacente. WCF Data
Services logra la independencia de almacenamiento separando el modelo conceptual que direcciona los
recursos indicados por OData del esquema especfico del origen de datos subyacente.
WCF Data Services se integra con ADO.NET Entity Framework para que puedan crearse servicios de datos
que exponen datos relacionales. Puede usar las herramientas de Entity Data Model para crear un modelo de
datos que contiene recursos direccionables como entidades y al mismo tiempo definir la asignacin entre
este modelo y las tablas de la base de datos subyacente.
WCF Data Services tambin le permite crear servicios de datos que exponen cualquier estructura de datos
que devuelva una implementacin de la interfaz IQueryable. Esto le permite crear servicios de datos que
exponen los datos procedentes de tipos de .NET Framework. Si tambin se implementa la interfaz
IUpdatable, se admiten las operaciones de creacin, actualizacin y eliminacin.
Para obtener una ilustracin de cmo se integra WCF Data Services con estos proveedores de datos, vea el
diagrama arquitectnico que se muestra ms adelante en este tema.

Lgica de negocios personalizada


WCF Data Services hace ms fcil agregar la lgica de negocios personalizada a un servicio de datos a
travs de operaciones de servicio e interceptores. Las operaciones de servicio son mtodos definidos en el
servidor direccionables a travs de URI con el mismo formato que los recursos de datos. Las operaciones de
servicio tambin pueden usar la sintaxis de las expresiones de consulta para filtrar, ordenar y paginar los
datos devueltos por una operacin. Por ejemplo, el URI

http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$orderby=OrderDate&$top=10&
$skip=10 representa una llamada a una operacin de servicio denominada GetOrdersByCity en el servicio
de datos de Northwind que devuelve los pedidos para los clientes residentes en Londres, con los resultados
paginados ordenados por OrderDate.
Los interceptores permiten integrar la lgica de la aplicacin personalizada en el procesamiento de los
mensajes de solicitud o respuesta de un servicio de datos. Se llama a los interceptores cuando se produce
una accin de consulta, insercin, actualizacin o eliminacin en el conjunto de entidades especificado.
Despus, un interceptor puede modificar los datos, aplicar la directiva de autorizacin o incluso terminar la
operacin. Los mtodos de interceptor se deben registrar explcitamente para un conjunto de entidades
determinado expuesto por un servicio de datos.

Bibliotecas de cliente
OData define un conjunto de modelos uniformes para interactuar con los servicios de datos. Esto
proporciona una oportunidad de crear componentes reutilizables que se basen en estos servicios, como las
bibliotecas del lado cliente que permiten usar servicios de datos ms fcilmente.
WCF Data Services incluye bibliotecas de cliente para aplicaciones cliente basadas en .NET Framework o en
Silverlight. Estas bibliotecas de cliente le permiten interactuar con los servicios de datos mediante objetos
de .NET Framework. Tambin admiten consultas basadas en objetos y consultas LINQ, carga de objetos
relacionados, seguimiento de cambios y resolucin de identidades.
Adems de las bibliotecas de cliente de OData incluidas con .NET Framework y con Silverlight, hay otras
bibliotecas de cliente que le permiten usar una fuente de OData en aplicaciones cliente, como PHP, AJAX y
las aplicaciones Java.

Informacin general de la arquitectura


En el siguiente diagrama se muestra la arquitectura de WCF Data Services para exponer fuentes de OData y
utilizarlas en bibliotecas de cliente habilitadas para OData :

MCT: Luis Dueas

Pag 3 de 128

WCF Data Service

MCT: Luis Dueas

Pag 4 de 128

WCF Data Service

3. Introduccin a WCF Data Services


Los temas de esta seccin le ayudan a comprender rpidamente Open Data Protocol (OData) y cmo usar
WCF Data Services para exponer y utilizar fuentes OData mediante la explicacin de las tecnologas
subyacentes. En esta seccin se incluyen contenido conceptual y un tutorial rpido.

3.1. Exponer los datos como servicio


WCF Data Services se integra con Visual Studio para permitirle definir con ms facilidad servicios para
exponer los datos como fuentes Open Data Protocol (OData) . La creacin de un servicio de datos que
expone una fuente OData supone la realizacin de los siguientes pasos bsicos:
1.

Definirel modelo de datos. WCF Data Services admite de forma nativa los modelos de datos
basados en ADO.NET Entity Framework. WCF Data Services tambin admite modelos de datos que
estn basados en los objetos de Common Language Runtime (CLR) que devuelven una instancia de
la interfaz IQueryable. Esto permite implementar servicios de datos que estn basados en listas,
matrices y colecciones en .NET Framework. Para habilitar las operaciones de creacin, actualizacin
y eliminacin sobre estas estructuras de datos, tambin debe implementar la interfaz IUpdatable.
Para escenarios ms avanzados, WCF Data Services incluye un conjunto de proveedores que le
permiten definir un modelo de datos basado en tipos de datos enlazados en tiempo de ejecucin.

2.

Crear el servicio de datos. El servicio de datos ms bsico expone una clase que hereda de la clase
DataService, con un tipo T que es el nombre completo del espacio de nombres del contenedor de
la entidad.

3.

Configurar el servicio de datos. De forma predeterminada, WCF Data Services deshabilita el


acceso a los recursos que expone un contenedor de entidades. La interfaz
DataServiceConfiguration le permite configurar el acceso a los recursos y las operaciones del
servicio, especificar la versin admitida de OData , as como definir otros comportamientos de todo
el servicio, como los comportamientos de las operaciones por lotes o el nmero mximo de
entidades que pueden devolverse en una nica respuesta.

3.2. Acceso a recursos del servicio de datos


WCF Data Services admite Open Data Protocol (OData) para exponer los datos como una fuente con
recursos direccionables a travs de identificadores uniformes de recursos (URI). Estos recursos se
representan segn las convenciones del modelo entidad-relacin de Entity Data Model. En este modelo, las
entidades representan unidades operacionales de datos que son tipos de datos en un dominio de
aplicacin, como clientes, pedidos, elementos y productos. El acceso a los datos de entidad y la
modificacin de los mismos se realiza usando la semntica de Representational State Transfer (REST),
especficamente los verbos HTTP estndar GET, PUT, POST y DELETE.

Direccionar recursos
En OData , podr direccionar los datos expuestos por el modelo de datos utilizando un URI. Por ejemplo, el
siguiente URI devuelve una fuente que representa el conjunto de entidades Customers, que contiene las
entradas de todas las instancias del tipo de entidad Customer:

http://services.odata.org/Northwind/Northwind.svc/Customers
Las entidades tienen propiedades especiales denominadas claves de entidad. Una clave de entidad se utiliza
para identificar una entidad nica de manera unvoca en un conjunto de entidades. Esto le permite
direccionar una instancia concreta de un tipo de entidad en el conjunto de entidades. Por ejemplo, el
siguiente URI devuelve la entrada de una instancia concreta del tipo de entidad Customer que tiene el valor
de clave ALFKI:

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')

MCT: Luis Dueas

Pag 5 de 128

WCF Data Service


Tambin se pueden direccionar individualmente las propiedades primitivas y complejas de una instancia de
entidad. Por ejemplo, el siguiente URI devuelve un elemento XML que contiene el valor de propiedad

ContactName para una entidad Customer concreta:


http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/ContactName
Al incluir el extremo $value en el URI anterior, en el mensaje de respuesta solamente se devuelve el valor de
la propiedad primitiva. En el siguiente ejemplo solo se devuelve la cadena "Maria Anders" sin el elemento
XML:

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/ContactName/$value
Las relaciones entre entidades se definen en el modelo de datos mediante asociaciones. Estas asociaciones
le permiten direccionar entidades relacionadas mediante propiedades de navegacin de una instancia de
entidad. Una propiedad de navegacin puede devolver una nica entidad relacionada, en el caso de una
relacin de varios a uno, o un conjunto de entidades relacionadas, en el caso de una relacin de uno a
varios. Por ejemplo, el siguiente URI devuelve una fuente que representa el conjunto de todas las entidades
Orders relacionadas con una entidad Customer concreta:

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders
Las relaciones, que son con frecuencia bidireccionales, estn representadas por un par de propiedades de
navegacin. Al contrario de la relacin mostrada en el ejemplo anterior, el siguiente URI devuelve una
referencia a la entidad Customer a la que pertenece una entidad Order concreta:

http://services.odata.org/Northwind/Northwind.svc/Orders(10643)/Customer
OData tambin le permite direccionar recursos basndose en los resultados de expresiones de consulta.
Esto permite filtrar conjuntos de recursos en funcin de una expresin evaluada. Por ejemplo, el siguiente
URI filtra los recursos para devolver a la entidad Customer especificada solo las entidades Orders (pedidos)
que se han distribuido desde el 22 de septiembre de 1997:

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders?$filter=ShippedDate gt
datetime'1997-09-22T00:00:00'

Opciones de consulta del sistema


OData define un conjunto de opciones de consulta del sistema que puede utilizar para realizar operaciones
de consulta tradicionales en los recursos, como filtrar, ordenar y paginar. Por ejemplo, el siguiente URI
devuelve el conjunto de todas las entidades Order, junto con las entidades Order_Detail relacionadas, cuyo
cdigo postal no termina en 100:

http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=not
endswith(ShipPostalCode,'100')&$expand=Order_Details&$orderby=ShipCity
Las entradas de la fuente devuelta se ordenan tambin en funcin del valor de la propiedad ShipCity de los
pedidos.
WCF Data Services admite las siguientes opciones de consulta del sistema de OData :
Opcin de
Descripcin
consulta
$orderby

Define un criterio de ordenacin predeterminado para las entidades de la fuente devuelta. La


siguiente consulta ordena la fuente de los clientes devuelta por provincia y ciudad:

http://services.odata.org/Northwind/Northwind.svc/Customers?$orderby=Country,City
$top

Especifica el nmero de entidades que se incluirn en la fuente devuelta. En el siguiente ejemplo


se omiten los 10 primeros clientes y, a continuacin, se devuelven los 10 siguientes:

http://services.odata.org/Northwind/Northwind.svc/Customers?$skip=10&$top=10
$skip

Especifica el nmero de entidades que se omitirn antes de empezar a devolver las entidades en
la fuente. En el siguiente ejemplo se omiten los 10 primeros clientes y, a continuacin, se
devuelven los 10 siguientes:

MCT: Luis Dueas

Pag 6 de 128

WCF Data Service


http://services.odata.org/Northwind/Northwind.svc/Customers?$skip=10&$top=10

$filter

Define una expresin que filtra las entidades devueltas en la fuente en funcin de criterios
concretos. Esta opcin de consulta admite un conjunto de operadores de comparacin lgicos,
operadores aritmticos y funciones de consulta predefinidas que se utilizan para evaluar la
expresin de filtro. En el siguiente ejemplo se devuelven todos los pedidos cuyo cdigo postal
no termina en 100:

http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=not
endswith(ShipPostalCode,'100')

$expand

Especifica qu entidades relacionadas devuelve la consulta. Las entidades relacionadas se


incluyen como una fuente o una entrada alineada con la entidad devuelta por la consulta. En el
siguiente ejemplo se devuelve el pedido del cliente 'ALFKI' junto con los detalles de artculos de
cada pedido:

http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders?
$expand=Order_Details
$format

Especifica el formato de la fuente devuelta. El formato predeterminado de la fuente es Atom.


Especifica una proyeccin que define las propiedades de la entidad devueltas en la proyeccin.
De forma predeterminada, todas las propiedades de una entidad se devuelven en una fuente. La

$select

siguiente consulta devuelve solo tres propiedades de la entidad Customer:

http://services.odata.org/Northwind/Northwind.svc/Customers?$select=CustomerID,Compa
nyName,City
$inlinecou
Solicita que un recuento del nmero de entidades devuelto en la fuente se incluya con la fuente.
nt

Direccionar relaciones
Adems de direccionar conjuntos de entidades e instancias de entidades, OData tambin le permite
direccionar las asociaciones que representan las relaciones entre las entidades. Esta funcionalidad es
necesaria para crear o cambiar una relacin entre dos instancias de entidades, como el expedidor
relacionado con un pedido determinado de la base de datos de ejemplo Northwind. OData admite un
operador $link para direccionar especficamente las asociaciones entre las entidades. Por ejemplo, el URI
siguiente se especifica en un mensaje de solicitud PUT de HTTP para que se use otro expedidor para el
pedido especificado.

http://services.odata.org/Northwind/Northwind.svc/Orders(10643)/$links/Shipper

Utilizar la fuente devuelta


El URI de un recurso de OData permite direccionar datos de entidad expuestos por el servicio. Al registrar
un URI en el campo de direccin de un explorador web, se devuelve una representacin de la fuente de
OData del recurso solicitado. Aunque un explorador web puede ser til para probar que un recurso del
servicio de datos devuelve los datos esperados, normalmente el acceso a los servicios de datos de
produccin -que tambin pueden crear, actualizar y eliminar datos- se realiza mediante cdigo de
aplicacin o lenguajes de scripting en una pgina web.

3.3. Usar un servicio de datos en una aplicacin cliente


Podr tener acceso a un servicio que exponga una fuente de Open Data Protocol (OData) proporcionando
un URI a un explorador web. El URI proporciona la direccin de un recurso y los mensajes de solicitud se
envan a estas direcciones para obtener acceso o cambiar los datos subyacentes que el recurso representa.
El explorador emite un comando GET de HTTP y devuelve el recurso solicitado como una fuente de OData .
Aunque un explorador web puede ser til para probar que un servicio de OData devuelve los datos
esperados, normalmente el acceso a los servicios de OData de produccin que le permiten crear, actualizar
y eliminar datos tambin se realiza mediante cdigo de aplicacin o lenguajes de scripts en una pgina web.

MCT: Luis Dueas

Pag 7 de 128

WCF Data Service


En este tema se proporciona informacin general acerca de cmo obtener acceso a las fuentes de OData
desde una aplicacin cliente.

Obtener acceso y cambiar datos mediante la semntica REST


OData contribuye a garantizar la interoperabilidad entre los servicios que exponen las fuentes de OData y
las aplicaciones que utilizan las fuentes de OData . Las aplicaciones tienen acceso a los datos y los cambian
en un servicio basado en OData enviando mensajes de solicitud de una accin HTTP concreta y con un URI
que direcciona un recurso de entidad sobre el que se debera realizar la accin. Cuando sea obligatorio
proporcionar datos de la entidad, se proporcionan mediante una carga especficamente codificada en el
cuerpo del mensaje.

Acciones HTTP
OData admite las siguientes acciones HTTP para realizar operaciones de creacin, lectura, actualizacin y
eliminacin en los datos de la entidad que el recurso direccionado representa:
GET de HTTP: es la accin predeterminada cuando se tiene acceso a un recurso desde un
explorador. No se proporciona ninguna carga en el mensaje de solicitud y se devuelve un mtodo
de respuesta con una carga que contiene los datos solicitados.
POST de HTTP: inserta los nuevos datos de entidad en el recurso proporcionado. Los datos que se
van a insertar se proporcionan en la carga del mensaje de solicitud. La carga del mensaje de
respuesta contiene los datos de la entidad recin creada. Esto incluye los valores de clave
generados automticamente. El encabezado tambin contiene el URI que direcciona el nuevo
recurso de entidad.
DELETE de HTTP: elimina los datos de entidad que representa el recurso especificado. En los
mensajes de solicitud o respuesta no hay presente ninguna carga.
PUT de HTTP: reemplaza los datos de la entidad existentes en el recurso solicitado con nuevos
datos que se proporcionan en la carga del mensaje de solicitud.
MERGE de HTTP: debido a las ineficacias a la hora de ejecutar una accin DELETE seguida de una
accin INSERT en el origen de datos nicamente para cambiar los datos de entidad, OData
presenta una nueva accin MERGE de HTTP. La carga del mensaje de solicitud contiene las
propiedades que se deben cambiar en el recurso de entidad direccionado. Dado que MERGE de
HTTP no se define en la especificacin HTTP, esto puede requerir un procesamiento adicional para
enrutar una solicitud MERGE de HTTP a travs de servidores que no usan.

Formatos de carga
Para una solicitud PUT, POST o MERGE de HTTP, la carga de un mensaje de solicitud contiene los datos de
entidad que el usuario enva al servicio de datos. El contenido de la carga depende del formato de datos del
mensaje. Las respuestas HTTP a todas las acciones, excepto DELETE, tambin contienen este tipo de carga.
OData admite los siguientes formatos de carga para tener acceso y cambiar los datos con el servicio:
Atom: codificacin de mensajes basada en XML definida por OData como una extensin del
Protocolo de publicacin Atom (AtomPub) para habilitar el intercambio de datos sobre HTTP para
fuentes web, podcasts, wikis y funcionalidad de Internet basada en XML.
JSON: JavaScript Object Notation (JSON) es un formato de intercambio de datos ligero que est
basado en un subconjunto del lenguaje de programacin JavaScript.
El formato de mensaje de la carga se solicita en el encabezado del mensaje de la solicitud HTTP.

Obtener acceso y cambiar datos mediante bibliotecas cliente


WCF Data Services incluye bibliotecas cliente que permiten utilizar ms fcilmente una fuente de OData en
.NET Framework y las aplicaciones cliente basadas en Silverlight. Estas bibliotecas simplifican el envo y

MCT: Luis Dueas

Pag 8 de 128

WCF Data Service


recepcin de los mensajes HTTP. Tambin traducen la carga del mensaje en objetos CLR que representan
los datos de entidad. Las bibliotecas cliente representan las dos clases principales DataServiceContext y
DataServiceQuery. Estas clases le permiten consultar un servicio de datos y, a continuacin, trabajar con los
datos de entidad devueltos como objetos CLR.
Puede usar el cuadro de dilogo Agregar referencia de servicio de Visual Studio para agregar una
referencia a un servicio de datos. Esta herramienta solicita metadatos de servicio desde un servicio de datos
al que se ha hecho referencia y genera el DataServiceContext que representa un servicio de datos, adems
de generar las clases de servicio de datos cliente que representan las entidades.
Existen bibliotecas de programacin que le permiten utilizar una fuente de OData en otros tipos de
aplicaciones cliente.

3.4. Tutorial rpido


Este tutorial rpido le ayudar a familiarizarse con WCF Data Services y Open Data Protocol (OData) a travs
de una serie de tareas relacionadas con los temas de Introduccin a WCF Data Services.

3.4.1. Crear el servicio de datos


En esta tarea, crear un servicio de datos de ejemplo que exponga una fuente de Open Data Protocol
(OData) basada en la base de datos de ejemplo Northwind. Esta tarea supone la realizacin de los siguientes
pasos bsicos:
1.

Cree una aplicacin web ASP.NET.

2.

Defina el modelo de datos usando las herramientas de Entity Data Model.

3.

Agregue el servicio de datos a la aplicacin web.

4.

Habilite el acceso al servicio de datos.

Nota:
La aplicacin web ASP.NET que crea al completar esta tarea se ejecuta en el servidor de desarrollo de
ASP.NET proporcionado por Visual Studio. Para facilitar la prueba y la solucin de problemas del servicio de
datos durante el desarrollo, puede ejecutar la aplicacin que hospeda el servicio de datos mediante Internet
Information Services (IIS).

Para crear la aplicacin web ASP.NET


1.
2.
3.
4.
5.
6.

En Visual Studio, en el men Archivo, seleccione Nuevo y, a continuacin, seleccione Proyecto.


En el cuadro de dilogo Nuevo proyecto, seleccione Visual Basic o Visual C# como el lenguaje de
programacin.
En el recuadro Plantillas, seleccione Aplicacin web ASP.NET. Nota: si usa Visual Studio Web
Developer, tendr que crear un nuevo sitio web en lugar de una nueva aplicacin web.
Escriba NorthwindService como nombre del proyecto.
Haga clic en Aceptar.
(Opcional) Especifique un nmero de puerto especfico para la aplicacin web. Nota: en el resto del
tutorial rpido se usa el nmero de puerto 12345.
a.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del


proyecto de ASP.NET que acaba de crear y, a continuacin, haga clic en Propiedades.

b.

Seleccione la pestaa Web y, a continuacin, establezca el valor del cuadro de testo


Puerto especfico en 12345.

Para definir el modelo de datos

MCT: Luis Dueas

Pag 9 de 128

WCF Data Service


1.
2.
3.
4.
5.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, seleccione Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione ADO.NET Entity Data Model.
Como nombre del modelo de datos, escriba Northwind.edmx.
En el Asistente para Entity Data Model, seleccione Generar desde la base de datos y, a
continuacin, haga clic en Siguiente.
Para conectar el modelo de datos a la base de datos efecte uno de los pasos siguientes y despus
haga clic en Siguiente:
o Si no tiene una conexin de base de datos ya configurada, haga clic en Nueva conexin y
cree una conexin nueva. Esta instancia de SQL Server debe tener adjuntada la base de
datos
de
ejemplo
Northwind.
o bien

6.
7.

Si tiene una conexin de base de datos ya configurada para conectarse a la base de datos
Northwind, seleccione esa conexin en la lista de conexiones.

En la pgina final del asistente, seleccione las casillas de todas las tablas de la base de datos y
desactive las casillas correspondientes a las vistas y los procedimientos almacenados.
Haga clic en Finalizar para cerrar el asistente.
Nota:
Este modelo de datos generado expone las propiedades de clave externa en los tipos de entidad.
Los modelos de datos creados mediante Visual Studio 2008 no incluyen estas propiedades de clave
externa. Debido a esto, debe actualizar las clases del servicio de datos de cliente de cualquier
aplicacin cliente que se haya creado para tener acceso al servicio de datos de Northwind que se
cre con Visual Studio 2008 antes de intentar tener acceso a esta versin del servicio de datos de
Northwind.

Para crear el servicio de datos


1.
2.
3.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, haga clic en Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione Servicio de datos de ADO.NET.
Como nombre del servicio, escriba Northwind.
Visual Studio crea los archivos de cdigo y marcado XML para el nuevo servicio. De forma
predeterminada, se abre la ventana del editor de cdigo. En el Explorador de soluciones, el
servicio tendr el nombre Northwind, con la extensin .svc.cs o .svc.vb.

4.

En el cdigo para el servicio de datos, reemplace el comentario /* TODO: put your data source

class name here */ de la definicin de la clase que define el servicio de datos por el tipo que es el
contenedor de entidades del modelo de datos, que en este caso es NorthwindEntities. La
definicin de la clase debera ser como la siguiente:
Public Class Northwind
Inherits DataService(Of NorthwindEntities)

Para habilitar el acceso a los recursos del servicio de datos


1.

En el cdigo del servicio de datos, reemplace el cdigo de marcador de posicin de la funcin

InitializeService por el siguiente:


' Grant only the rights needed to support the client application.
config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead _
Or EntitySetRights.WriteMerge _

MCT: Luis Dueas

Pag 10 de 128

WCF Data Service


Or EntitySetRights.WriteReplace)
config.SetEntitySetAccessRule("Order_Details", EntitySetRights.AllRead _
Or EntitySetRights.AllWrite)
config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead)

De esta forma, los clientes autorizados pueden tener acceso de lectura y escritura a los recursos
para los conjuntos de entidades especificados.
Nota:
Cualquier cliente que pueda tener acceso a la aplicacin ASP.NET tambin puede tener acceso a los
recursos expuestos por el servicio de datos. En un servicio de datos de produccin, para evitar el
acceso no autorizado a los recursos tambin debera proteger la aplicacin.

3.4.2. Obtener acceso al servicio desde un explorador Web


En esta tarea, iniciar WCF Data Services desde Visual Studio y, opcionalmente, deshabilitar la lectura de
fuentes en el explorador web. A continuacin, recuperar el documento de definicin de servicio y tendr
acceso a los recursos del servicio de datos enviando solicitudes HTTP GET a travs de un explorador web a
los recursos expuestos.
Nota:
De forma predeterminada, Visual Studio asigna automticamente un nmero de puerto al URI localhost en
el equipo. En esta tarea se usa el nmero de puerto 12345 en los ejemplos de URI.

Para solicitar el documento de servicio predeterminado utilizando Internet


Explorer
1.

Seleccione Opciones de Internet en el men Herramientas de Internet Explorer, haga clic en la


pestaa Contenido, en la opcin Configuracin de la seccin Fuentes y desactive Activar la vista
de lectura de fuentes.
De este modo, se garantiza que la lectura de fuentes queda deshabilitada. Si no deshabilita esta
funcionalidad, el explorador web tratar el documento codificado como AtomPub devuelto como si
fuera una fuente XML en lugar de mostrar los datos XML sin formato.
Nota:
Si el explorador no puede mostrar la fuente como datos XML sin formato, todava debera poder
ver la fuente como el cdigo fuente de la pgina.

2.
3.

En Visual Studio, presione la tecla F5 para iniciar la depuracin de la aplicacin.


Abra un explorador web en el equipo local. En la barra de direcciones, escriba el siguiente URI:

http://localhost:12345/northwind.svc
De esta forma, se devuelve el documento de servicio predeterminado, que contiene una lista de los
conjuntos de entidades expuestos por este servicio de datos.

Para tener acceso a los recursos del conjunto de entidades desde un explorador
web
1.

En el campo de la barra de direcciones del explorador web, escriba el URI siguiente:

http://localhost:12345/northwind.svc/Customers
De esta forma, se devuelve un conjunto de todos los clientes de la base de datos de ejemplo
Northwind.
2.

En el campo de la barra de direcciones del explorador web, escriba el URI siguiente:

MCT: Luis Dueas

Pag 11 de 128

WCF Data Service


http://localhost:12345/northwind.svc/Customers('ALFKI')
De esta forma, se devuelve una instancia de la entidad para un cliente concreto, ALFKI.
3.

En el campo de la barra de direcciones del explorador web, escriba el URI siguiente:

http://localhost:12345/northwind.svc/Customers('ALFKI')/Orders
De esta forma, se recorre la relacin entre clientes y pedidos para devolver un conjunto de todos
los pedidos para ese cliente, ALFKI.
4.

En el campo de la barra de direcciones del explorador web, escriba el URI siguiente:

http://localhost:12345/northwind.svc/Customers('ALFKI')/Orders?$filter=OrderID eq 10643
De esta forma, se filtran los pedidos que pertenecen a un cliente determinado, ALFKI, de modo
que solo se devuelve un pedido concreto dependiendo del valor proporcionado para OrderID.

3.4.3. Crear la aplicacin cliente de .NET Framework


Esta es la tarea final del tutorial rpido de WCF Data Services . En esta tarea, agregar una aplicacin de
consola a la solucin, agregar una referencia a la fuente de Open Data Protocol (OData) en esta nueva
aplicacin cliente y obtendr acceso a la fuente de OData desde la aplicacin cliente usando las clases del
servicio de datos del cliente y las bibliotecas de cliente generadas.
Nota:
No es necesaria una aplicacin cliente basada en .NET Framework para obtener acceso a una fuente de
datos. Cualquier componente de aplicacin que utilice una fuente de OData puede tener acceso al servicio
de datos.

Para crear la aplicacin cliente mediante Visual Studio


1.
2.
3.
4.

En el Explorador de soluciones, haga clic con el botn secundario en la solucin, despus haga
clic en Agregar y, a continuacin, en Nuevo proyecto.
En Tipos de proyecto, haga clic en Windows y, a continuacin, seleccione Aplicacin WPF en el
recuadro Templates.
Escriba NorthwindClient como nombre del proyecto y haga clic en Aceptar.
Abra el archivo Window1.xaml y reemplace el cdigo XAML por el cdigo siguiente:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Northwind Orders" Height="335" Width="425"
Name="OrdersWindow" Loaded="Window1_Loaded">
<Grid Name="orderItemsGrid">
<ComboBox DisplayMemberPath="OrderID" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="true"
Height="23" Margin="92,12,198,0" Name="comboBoxOrder" VerticalAlignment="Top"/>
<DataGrid ItemsSource="{Binding Path=Order_Details}"
CanUserAddRows="False" CanUserDeleteRows="False"
Name="orderItemsDataGrid" Margin="34,46,34,50"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Product" Binding="{Binding ProductID, Mode=OneWay}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity, Mode=TwoWay}" />
<DataGridTextColumn Header="Price" Binding="{Binding UnitPrice, Mode=TwoWay}" />
<DataGridTextColumn Header="Discount" Binding="{Binding Discount, Mode=TwoWay}" />

MCT: Luis Dueas

Pag 12 de 128

WCF Data Service


</DataGrid.Columns>
</DataGrid>
<Label Height="28" Margin="34,12,0,0" Name="orderLabel" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="65">Order:</Label>
<StackPanel Name="Buttons" Orientation="Horizontal" HorizontalAlignment="Right"
Height="40" Margin="0,257,22,0">
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12"
Name="buttonSave" VerticalAlignment="Bottom" Width="75"
Click="buttonSaveChanges_Click">Save Changes
</Button>
<Button Height="23" Margin="0,0,12,12"
Name="buttonClose" VerticalAlignment="Bottom" Width="75"
Click="buttonClose_Click">Close</Button>
</StackPanel>
</Grid>
</Window>

Para agregar al proyecto una referencia al servicio de datos


1.

Haga clic con el botn secundario en el proyecto NorthwindClient, haga clic en Agregar referencia
de servicio y, a continuacin, haga clic en Detectar.
De este modo se muestra el servicio de datos de Northwind que cre en la primera tarea.

2.

En el cuadro de texto Espacio de nombres, escriba Northwind y, a continuacin, haga clic en


Aceptar.
De este modo se agrega un nuevo archivo de cdigo al proyecto, que contiene las clases de datos
que se usan para obtener acceso e interactuar con los recursos del servicio de datos como objetos.
Las clases de datos se crean en el espacio de nombres NorthwindClient.Northwind.

Para tener acceso a los datos del servicio de datos en la aplicacin WPF
1.
2.

En el Explorador de soluciones, en NorthwindClient, haga clic con el botn secundario en el


proyecto y haga clic en Agregar referencia.
En el cuadro de dilogo Agregar referencia, haga clic en la pestaa .NET, seleccione el ensamblado
System.Data.Services.Client.dll y, a continuacin, haga clic en Aceptar. En el Explorador de
soluciones, en NorthwindClient, abra la pgina de cdigo para el archivo Window1.xaml y
agregue la instruccin using siguiente (Imports en Visual Basic).
Imports System.Data.Services.Client
Imports NorthwindClient.Northwind

3.

Inserte el cdigo siguiente que consulta al servicio de datos y enlaza el resultado a una instancia de
DataServiceCollection en la clase Window1:
Nota:
Debe reemplazar el nombre de host localhost:12345 por el servidor y el puerto en que se hospeda
la instancia del servicio de datos de Northwind.
Private context As NorthwindEntities
Private customerId As String = "ALFKI"
' Replace the host server and port number with the values
' for the test server hosting your Northwind data service instance.
Private svcUri As Uri = New Uri("http://localhost:12345/Northwind.svc")

MCT: Luis Dueas

Pag 13 de 128

WCF Data Service


Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Instantiate the DataServiceContext.
context = New NorthwindEntities(svcUri)
' Define a LINQ query that returns Orders and
' Order_Details for a specific customer.
Dim ordersQuery = From o In context.Orders.Expand("Order_Details") _
Where o.Customer.CustomerID = customerId _
Select o
' Create an DataServiceCollection(Of T) based on
' execution of the LINQ query for Orders.
Dim customerOrders As DataServiceCollection(Of Order) = New _
DataServiceCollection(Of Order)(ordersQuery)
' Make the DataServiceCollection<T> the binding source for the Grid.
Me.orderItemsGrid.DataContext = customerOrders
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub

4.

Inserte el cdigo siguiente que sirve para guardar los cambios en la clase Window1:
Private Sub buttonSaveChanges_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Save changes made to objects tracked by the context.
context.SaveChanges()
Catch ex As DataServiceRequestException
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub buttonClose_Click(ByVal sender As Object, ByVal a As RoutedEventArgs)
Me.Close()
End Sub

Para compilar y ejecutar la aplicacin NorthwindClient


1.
2.

En el Explorador de soluciones, haga clic con el botn secundario en el proyecto NorthwindClient


y seleccione Establecer como proyecto de inicio.
Presione F5 para iniciar la aplicacin.
Se compila la solucin y se inicia la aplicacin cliente. Los datos se recuperan del servicio y se
muestran en la consola.

3.

Edite un valor de la columna Cantidad de la cuadrcula de datos y, a continuacin, haga clic en


Guardar.
Los cambios se guardan en el servicio de datos.
Nota:
Esta versin de la aplicacin NorthwindClient no admite agregar ni eliminar entidades.

3.5. Escenarios de las aplicaciones


WCF Data Services admite un conjunto bsico de escenarios para exponer y utilizar datos cuando fuentes de
Open Data Protocol (OData) . Este tema remite a los temas importantes en estos escenarios.

MCT: Luis Dueas

Pag 14 de 128

WCF Data Service


Exponga datos relacionales de una base de datos como una fuente de OData .
Tutorial rpido (WCF Data Services)
Exponer los datos como servicio (WCF Data Services)
Cmo: Crear un servicio de datos mediante un origen de datos de ADO.NET Entity
Framework (WCF Data Services)
Exponga clases de datos de CLR arbitrarias como una fuente de OData .
Exponer los datos como servicio (WCF Data Services)
Cmo: Crear un servicio de datos mediante el proveedor de reflexin (WCF Data Services)
Proveedores de servicios de datos (WCF Data Services)
Utilice una fuente de OData en una aplicacin cliente basada en .NET Framework.
Tutorial rpido (WCF Data Services)
Usar un servicio de datos en una aplicacin cliente (WCF Data Services)
Biblioteca de cliente de WCF Data Services
Utilice una fuente de OData en una aplicacin cliente basada en Silverlight.
WCF Data Services (Silverlight)
Operaciones asincrnicas (WCF Data Services)
How to: Bind Data Service Data to Controls (WCF Data Services/Silverlight)
Utilice una fuente de OData en una aplicacin cliente basada en AJAX.
Usar un servicio de datos en una aplicacin cliente (WCF Data Services)
OData
Cree una solucin de datos de extremo a extremo que use OData para transferir datos entre el cliente y el
servidor.
Tutorial rpido (WCF Data Services)
Usar un servicio de datos en una aplicacin cliente (WCF Data Services)
Biblioteca de cliente de WCF Data Services
Cree una aplicacin cliente basada en .NET Framework utiliza una fuente de OData de forma asincrnica
para evitar los problemas de latencia en el cliente.
Cmo: Ejecutar consultas de servicio de datos asincrnicos (WCF Data Services)
Operaciones asincrnicas (WCF Data Services)
WCF Data Services (Silverlight)
Exponga y utilice una fuente de OData con un objeto binario grande al que se obtiene acceso y se cambia
como una secuencia.
Proveedores de transmisin por secuencias (WCF Data Services)
Trabajar con datos binarios (Servicios de datos de WCF)
Enlace fuentes de OData a controles en una aplicacin de Windows Presentation Framework (WPF).
Enlazar datos a controles (WCF Data Services)
Cmo: Enlazar datos a los elementos de Windows Presentation Foundation (WCF Data
Services)
Cmo: Enlazar datos mediante un origen de datos del proyecto (WCF Data Services)
Intercepte los mensajes que entran al servicio de datos para realizar la validacin de datos y el filtrado de
consultas basado en roles.

MCT: Luis Dueas

Pag 15 de 128

WCF Data Service


Cmo: Interceptar mensajes del servicio de datos (WCF Data Services)
Interceptores (WCF Data Services)
Cree extremos en un servicio de datos para habilitar comportamientos de servicio personalizados.
Cmo: Definir una operacin de servicio (WCF Data Services)
Operaciones de servicio (WCF Data Services)

4. Definir WCF Data Services


En esta seccin se describe cmo crear y configurar WCF Data Services para exponer datos como fuente
Open Data Protocol (OData) .

4.1. Configurar el servicio de datos


Con WCF Data Services , puede crear servicios de datos que expongan fuentes de Open Data Protocol
(OData) . Los datos de estas fuentes pueden provenir de distintos orgenes de datos. WCF Data Services usa
proveedores de datos para exponer estos datos como fuente de OData . Estos proveedores incluyen un
proveedor de Entity Framework , un proveedor de reflexin y un conjunto de interfaces de proveedor de
servicio de datos personalizados. La implementacin del proveedor define el modelo de datos del servicio.
En WCF Data Services , un servicio de datos es una clase que hereda de la clase DataService, donde el tipo
del servicio de datos es el contenedor de entidades del modelo de datos. Este contenedor de entidades
tiene una o varias propiedades que devuelven una interfaz IQueryable, que se usa para tener acceso a los
conjuntos de entidades del modelo de datos.
Los miembros de la clase DataServiceConfiguration definen los comportamientos del servicio de datos junto
con los miembros de la clase DataServiceBehavior, a la que se tiene acceso desde la propiedad
DataServiceBehavior de la clase DataServiceConfiguration. La clase DataServiceConfiguration se
proporciona al mtodo InitializeService que implementa el servicio de datos, como en la siguiente
implementacin de un servicio de datos de Northwind:
' This method is called only once to initialize service-wide policies.
Public Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
' Set the access rules of feeds exposed by the data service, which is
' based on the requirements of client applications.
config.SetEntitySetAccessRule("Customers", EntitySetRights.ReadSingle)
config.SetEntitySetAccessRule("Employees", EntitySetRights.ReadSingle)
config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead _
And EntitySetRights.WriteAppend _
And EntitySetRights.WriteMerge)
config.SetEntitySetAccessRule("Order_Details", EntitySetRights.All)
config.SetEntitySetAccessRule("Products", EntitySetRights.ReadMultiple)
' Set page size defaults for the data service.
config.SetEntitySetPageSize("Orders", 20)
config.SetEntitySetPageSize("Order_Details", 50)
config.SetEntitySetPageSize("Products", 50)
' Paging requires v2 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion = _
System.Data.Services.Common.DataServiceProtocolVersion.V2
End Sub

Configuracin del servicio de datos


La clase DataServiceConfiguration permite especificar los comportamientos siguientes del servicio de
datos.
Miembro
Comportamiento

MCT: Luis Dueas

Pag 16 de 128

WCF Data Service


AcceptCountRequests

Permite deshabilitar las solicitudes de recuento que se envan al servicio de


datos usando el segmento de ruta de acceso $count y la opcin de
consulta $inlinecount.

AcceptProjectionRequests

Permite deshabilitar la compatibilidad con la proyeccin de los datos en las


solicitudes que se envan al servicio de datos usando la opcin de consulta
$select.

EnableTypeAccess

Permite exponer un tipo de datos en los metadatos para un proveedor de


metadatos
dinmico
definido
mediante
la
interfaz
IDataServiceMetadataProvider.

EnableTypeConversion

Permite especificar si el motor en tiempo de ejecucin del servicio de datos


debe convertir el tipo contenido de la carga en el tipo de propiedad real
que se especifica en la solicitud.

Permite especificar si se invocan o no interceptores de cambio registrados


InvokeInterceptorsOnLinkDelete en las entidades relacionadas cuando se elimina un vnculo de relacin
entre dos entidades.
MaxBatchCount

Permite limitar el nmero de conjuntos de cambios y operaciones de


consulta que se permiten en un solo lote.

MaxChangesetCount

Permite limitar el nmero mximo de cambios que se pueden incluir en un


solo conjunto de cambios.

MaxExpandCount

Permite limitar el tamao de una respuesta limitando el nmero de


entidades relacionadas que pueden incluirse en una sola solicitud
utilizando el operador de consulta $expand.

MaxExpandDepth

Permite limitar el tamao de una respuesta limitando la profundidad del


grfico de entidades relacionadas que pueden incluirse en una sola
solicitud utilizando el operador de consulta $expand.

MaxObjectCountOnInsert

Permite limitar el nmero de entidades que se van a insertar que puede


contener una sola solicitud POST.

MaxProtocolVersion

Define la versin del protocolo Atom utilizado por el servicio de datos.


Cuando el valor de la propiedad MaxProtocolVersion se establece en un
valor
menor
que
el
valor
mximo
de
la
enumeracin
DataServiceProtocolVersion, la funcionalidad ms reciente de WCF Data
Services no est disponible para los clientes que tengan acceso al servicio
de datos.

MaxResultsPerCollection

Permite limitar el tamao de una respuesta limitando el nmero de


entidades de cada conjunto de entidades que se devuelve como fuente de
distribucin de datos.

RegisterKnownType

Agrega un tipo de datos a la lista de tipos reconocidos por el servicio de


datos.

SetEntitySetAccessRule

Establece los derechos de acceso para los recursos del conjunto de


entidades que estn disponibles en el servicio de datos. Se puede
proporcionar el valor asterisco (* para el parmetro de nombre para
establecer el acceso en el mismo nivel para todos los conjuntos de
entidades restantes. Se recomienda establecer el acceso a los conjuntos de
entidades para proporcionar el acceso con privilegios mnimos a los
recursos del servicio de datos requeridos por las aplicaciones cliente.

SetEntitySetPageSize

Establece el tamao de pgina mximo de un recurso de conjunto de


entidades.

Establece los derechos de acceso para las operaciones de servicio definidas


en el servicio de datos. Se puede proporcionar el valor asterisco (*) para el
parmetro de nombre con objeto de establecer el acceso en el mismo nivel
SetServiceOperationAccessRule para todas las operaciones de servicio. Se recomienda establecer el acceso
a las operaciones de servicio para proporcionar el acceso con privilegios
mnimos a los recursos del servicio de datos requeridos por las aplicaciones
cliente.

MCT: Luis Dueas

Pag 17 de 128

WCF Data Service

UseVerboseErrors

Esta propiedad de configuracin le permite solucionar ms fcilmente los


problemas de un servicio de datos devolviendo ms informacin en el
mensaje de respuesta del error. Esta opcin no est pensada para su uso en
un entorno de produccin.

Requisitos mnimos de acceso a recursos


En la siguiente tabla se detallan los derechos mnimos del conjunto de entidades que se deben conceder
para ejecutar una operacin concreta. Los ejemplos de ruta de acceso se basan en el servicio de datos de
Northwind que se crea al completar el tutorial rpido. Dado que la enumeracin EntitySetRights y la
enumeracin ServiceOperationRights se definen usando la clase FlagsAttribute, puede usar un operador OR
lgico con el fin de especificar varios permisos para una operacin o un conjunto de entidades nicos.
Ruta de acceso/accin
GET
DELETE
MERGE
POST
PUT

/Customers

ReadMultiple No compatible

/Customers('ALFKI')

ReadSingle

No
compatible

ReadSingle y ReadSingle y
ReadSingle y
no disponible
WriteDelete
WriteMerge
WriteReplace

Customers:

Customers:
ReadSingle
/Customers('ALFKI')/Orders

-y-

No compatible

No
compatible

Orders:
ReadMultiple
Customers:
ReadSingle
/Customers('ALFKI')/
Orders(10643)

-y-

Orders:
ReadSingle
Customers:
ReadSingle
/Orders(10643)/Customer

-y-

Orders:
ReadSingle

Orders

-y-

ReadSingle y
WriteMerge o
WriteReplace
-y-

No
compatible

Orders : y
WriteAppend
Customers:
ReadSingle

Customers:
ReadSingle

-y-

-y-

Orders:

Orders:

Customers:
ReadSingle
No compatible

-y-

Orders:

ReadSingle y ReadSingle y
WriteDelete WriteMerge

ReadSingle y
WriteReplace

Customers:
Customers: Customers:
ReadSingle y ReadSingle y WriteAppend
WriteDelete WriteMerge;
-yNo
-y-ycompatible
Orders:

Orders:

ReadSingle

ReadSingle

Customers:
ReadSingle
/Customers('ALFKI')/$links/

No
compatible

WriteAppend

No compatible

No
compatible

Orders:
ReadMultiple

Orders:
WriteAppend
y ReadSingle
Customers:
ReadSingle y
WriteMerge o
WriteReplace
-y-

No
compatible

Orders:
ReadSingle

/Customers('ALFKI')/$links/
MCT: Luis Dueas

Customers:

Customers:

No

No compatible No

Pag 18 de 128

WCF Data Service


Orders(10643)

ReadSingle
-y-

Orders:
ReadSingle

ReadSingle y compatible
WriteMerge o
WriteReplace
-y-

Orders:
ReadSingle
Customers:
ReadSingle

Customers:
ReadSingle
/Orders(10643)/$links/
Customer

/Customers/$count
/Customers('ALFKI')/
ContactName
/Customers('ALFKI')/Address/
StreetAddress/$value 1
/Customers('ALFKI')/
ContactName/$value

compatible

Customers:
ReadSingle;

Orders:
-yReadSingle y - y -yNo compatible
WriteMerge o
WriteReplace Orders:
Orders:
Orders:
ReadSingle y
ReadSingle y
ReadSingle
WriteMerge
WriteReplace
No
No
ReadMultiple No compatible
No compatible
compatible
compatible
ReadSingle

No compatible WriteMerge No compatible WriteReplace

ReadSingle

WriteDelete

ReadSingle

ReadSingle y
WriteMerge No compatible WriteReplace
WriteDelete

/Customers('ALFKI')/$value 2 ReadSingle

No
compatible

No compatible

No
compatible

No compatible

No
compatible

No compatible WriteReplace

No compatible

No
compatible

No
Customers:
WriteAppend compatible

No compatible

No
compatible

No compatible

Customers:
ReadSingle
/Customers?$select=Orders/
*&$expand=Orders

-y-

Orders:
ReadMultiple
Customers:
ReadSingle
/Customers('ALFKI')?$select=
Orders/ *&$expand=Orders

-y-

No
compatible

Orders:
ReadMultiple
1
En este ejemplo, Address representa una propiedad de tipo complejo de la entidad Customers que tiene
una propiedad denominada StreetAddress. El modelo utilizado por los servicios de datos de Northwind no
define este tipo complejo explcitamente. Cuando el modelo de datos se define con el proveedor de Entity
Framework , puede usar las herramientas de Entity Data Model para definir este tipo complejo.
2
Se admite este URI cuando una propiedad que devuelve un objeto binario grande (BLOB) se define como
el recurso multimedia que pertenece a una entidad que es una entrada de vnculo multimedia que, en este
caso, es Customers.

Requisitos de control de versiones

MCT: Luis Dueas

Pag 19 de 128

WCF Data Service


Los siguientes comportamientos de configuracin del servicio de datos requieren la versin 2 del protocolo
OData o versiones posteriores:
Compatibilidad para las solicitudes de recuento.
Compatibilidad para la opcin de consulta $select de proyeccin.

4.1.1. Cmo: Desarrollar un servicio de datos WCF que se ejecuta


en IIS
En este tema se muestra cmo utilizar WCF Data Services para crear un servicio de datos basado en la base
de datos de ejemplo Northwind que est hospedada en una aplicacin web ASP.NET que se ejecuta en
Internet Information Services (IIS).
Nota:
Para crear el servicio de datos de Northwind, debe tener instalada la base de datos de ejemplo Northwind
en su equipo local.
En este tema se muestra cmo crear un servicio de datos utilizando el proveedor de Entity Framework. Estn
disponibles otros proveedores de servicios de datos.
Una vez creado el servicio, debe proporcionar acceso a los recursos del servicio de datos de forma explcita.

Para crear la aplicacin web ASP.NET que se ejecuta en IIS


1.
2.
3.
4.
5.
6.
7.
8.
9.

En Visual Studio, en el men Archivo, seleccione Nuevo y, a continuacin, seleccione Proyecto.


En el cuadro de dilogo Nuevo proyecto, seleccione Visual Basic o Visual C# como el lenguaje de
programacin.
En el recuadro Plantillas, seleccione Aplicacin web ASP.NET. Nota: si usa Visual Studio Web
Developer, tendr que crear un nuevo sitio web en lugar de una nueva aplicacin web.
Escriba NorthwindService como nombre del proyecto.
Haga clic en Aceptar.
En el men Proyecto, seleccione Propiedades de NorthwindService.
Seleccione la pestaa Web y a continuacin, haga clic en Usar servidor web de IIS local.
Haga clic en Crear directorio virtual y, a continuacin, en Aceptar.
Ejecute el siguiente comando en el smbolo del sistema:
"%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -i

De este modo, se garantiza que Windows Communication Foundation (WCF) se registra en el


equipo.
10. Mediante SQL Server Management Studio o la utilidad sqlcmd.exe, ejecute el siguiente comando
de Transact-SQL con la instancia de SQL Server que tenga la base de datos Northwind asociada:
CREATE LOGIN [NT AUTHORITY\NETWORK SERVICE] FROM WINDOWS;
GO

De este modo, se crea un inicio de sesin en la instancia de SQL Server para la cuenta de Windows
utilizada para ejecutar IIS. Esto permite a IIS conectarse a la instancia de SQL Server.
11. Con la base de datos Northwind asociada, ejecute los siguientes comandos de Transact-SQL:
USE Northwind
GO
CREATE USER [NT AUTHORITY\NETWORK SERVICE]
FOR LOGIN [NT AUTHORITY\NETWORK SERVICE] WITH DEFAULT_SCHEMA=[dbo];
GO
ALTER LOGIN [NT AUTHORITY\NETWORK SERVICE]
WITH DEFAULT_DATABASE=[Northwind];
GO
EXEC sp_addrolemember 'db_datareader', 'NT AUTHORITY\NETWORK SERVICE'
GO
EXEC sp_addrolemember 'db_datawriter', 'NT AUTHORITY\NETWORK SERVICE'
GO

MCT: Luis Dueas

Pag 20 de 128

WCF Data Service


Esto otorga derechos al inicio de sesin nuevo, lo que permite a IIS leer y escribir datos en la base
de datos Northwind.

Para definir el modelo de datos


1.
2.
3.
4.
5.

6.
7.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, seleccione Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione ADO.NET Entity Data Model.
Como nombre del modelo de datos, escriba Northwind.edmx.
En el Asistente para Entity Data Model, seleccione Generar desde la base de datos y, a
continuacin, haga clic en Siguiente.
Para conectar el modelo de datos a la base de datos efecte uno de los pasos siguientes y despus
haga clic en Siguiente:
o Si no tiene una conexin de base de datos ya configurada, haga clic en Nueva conexin y
cree una conexin nueva. Esta instancia de SQL Server debe tener adjuntada la base de
datos
de
ejemplo
Northwind.
o bien
o Si tiene una conexin de base de datos ya configurada para conectarse a la base de datos
Northwind, seleccione esa conexin en la lista de conexiones.
En la pgina final del asistente, seleccione las casillas de todas las tablas de la base de datos y
desactive las casillas correspondientes a las vistas y los procedimientos almacenados.
Haga clic en Finalizar para cerrar el asistente.
Nota:
Este modelo de datos generado expone las propiedades de clave externa en los tipos de entidad.
Los modelos de datos creados mediante Visual Studio 2008 no incluyen estas propiedades de clave
externa. Debido a esto, debe actualizar las clases del servicio de datos de cliente de cualquier
aplicacin cliente que se haya creado para tener acceso al servicio de datos de Northwind que se
cre con Visual Studio 2008 antes de intentar tener acceso a esta versin del servicio de datos de
Northwind.

Para crear el servicio de datos


1.
2.
3.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, seleccione Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione Servicio de datos de ADO.NET.
Como nombre del servicio, escriba Northwind.
Visual Studio crea los archivos de cdigo y marcado XML para el nuevo servicio. De forma
predeterminada, se abre la ventana del editor de cdigo. En el Explorador de soluciones, el
servicio tendr el nombre Northwind, con la extensin .svc.cs o .svc.vb.

4.

En el cdigo para el servicio de datos, reemplace el comentario /* TODO: put your data source

class name here */ de la definicin de la clase que define el servicio de datos por el tipo que es el
contenedor de entidades del modelo de datos, que en este caso es NorthwindEntities. La
definicin de la clase debera ser como la siguiente:
Public Class Northwind
Inherits DataService(Of NorthwindEntities)

4.1.2. Cmo: Habilitar el acceso al servicio de datos


En WCF Data Services , debe permitir explcitamente el acceso a los recursos expuestos por un servicio de
datos. Esto significa que despus de crear un nuevo servicio de datos, debe proporcionar explcitamente
acceso a los recursos individuales como conjuntos de entidades. En este tema se muestra cmo permitir el
acceso de lectura y escritura a cinco conjuntos de entidades del servicio de datos de Northwind que se crea

MCT: Luis Dueas

Pag 21 de 128

WCF Data Service


al completar el tutorial rpido. Dado que la enumeracin EntitySetRights se define utilizando FlagsAttribute,
puede utilizar un operador OR lgico para especificar varios permisos para un nico conjunto de entidades.
Nota:
Cualquier cliente que pueda tener acceso a la aplicacin ASP.NET tambin puede tener acceso a los recursos
expuestos por el servicio de datos. En un servicio de datos de produccin, para evitar el acceso no
autorizado a los recursos, tambin debera proteger la aplicacin.

Para habilitar el acceso al servicio de datos


En el cdigo del servicio de datos, reemplace el cdigo de marcador de posicin de la funcin

InitializeService por el siguiente:


' Grant only the rights needed to support the client application.
config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead _
Or EntitySetRights.WriteMerge _
Or EntitySetRights.WriteReplace)
config.SetEntitySetAccessRule("Order_Details", EntitySetRights.AllRead _
Or EntitySetRights.AllWrite)
config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead)

De esta forma, los clientes pueden tener acceso de lectura y escritura a los conjuntos de entidades
de Orders y Order_Details, y acceso de solo lectura a los conjuntos de entidades de Customers.

4.1.3. Como: Habilitar la paginacin de los resultados del servicio


de datos
WCF Data Services le permite limitar el nmero de entidades devueltas por una consulta al servicio de
datos. Los lmites de pgina se definen en el mtodo que se llama cuando se inicializa el servicio y se
pueden establecer por separado para cada conjunto de entidades.
Si est habilitada la paginacin, la ltima entrada de la fuente contiene un vnculo a la pgina de datos
siguiente.
En este tema se muestra cmo modificar un servicio de datos para habilitar la paginacin de los conjuntos
de entidades Customers y Orders devueltos. En el ejemplo de este tema se usa el servicio de datos de
ejemplo Northwind.

Cmo habilitar la paginacin de los conjuntos de entidades Customers y Orders


devueltos
En el cdigo del servicio de datos, reemplace el cdigo de marcador de posicin de la funcin
InitializeService por el siguiente:
' Set page size defaults for the data service.
config.SetEntitySetPageSize("Orders", 20)
config.SetEntitySetPageSize("Order_Details", 50)
config.SetEntitySetPageSize("Products", 50)
' Paging requires v2 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion = _
System.Data.Services.Common.DataServiceProtocolVersion.V2

4.2. Proveedores de servicios de datos


WCF Data Services admite varios modelos de proveedor para exponer los datos como una fuente Open
Data Protocol (OData) . En este tema se proporciona informacin con el fin de permitirle seleccionar el
proveedor de WCF Data Services ms adecuado para su origen de datos.

Proveedores de orgenes de datos


MCT: Luis Dueas

Pag 22 de 128

WCF Data Service


WCF Data Services admite los siguientes proveedores para definir el modelo de datos de un servicio de
datos.
Proveedor
Descripcin

Proveedor de Entity
Framework

Este proveedor utiliza ADO.NET Entity Framework para permitir el uso de datos
relacionales con un servicio de datos definiendo un modelo de datos que se asigne a
datos relacionales. Su origen de datos puede ser SQL Server o cualquier otro origen
de datos con compatibilidad de otros proveedores para Entity Framework. Debera
usar el proveedor de Entity Framework cuando tenga un origen de datos relacional,
como una base de datos SQL Server.

Proveedor de
reflexin

Este proveedor utiliza la reflexin para permitir la definicin de un modelo de datos


basado en las clases de datos existente que se pueden exponer como instancias de la
interfaz IQueryable. Las actualizaciones se habilitan implementando la interfaz
IUpdatable. Debe usar este proveedor cuando tenga clases de datos estticas que se
definen en tiempo de ejecucin, como aquellas generadas por LINQ para SQL o las
definidas por un conjunto de datos con tipo.

Proveedores de
servicios de datos
personalizados

WCF Data Services incluye un conjunto de proveedores que le permiten definir de


forma dinmica un modelo de datos basado en tipos de datos enlazados en tiempo
de ejecucin. Debera implementar estas interfaces cuando no se conozcan los datos
que se estn exponiendo, cuando se est diseando la aplicacin o cuando los
proveedores de Entity Framework o de reflexin no sean suficientes.

Otros proveedores de servicios de datos


WCF Data Services tiene el siguiente proveedor de servicios de datos adicional que mejora el rendimiento
de un origen de datos definido mediante uno de los otros proveedores.
Proveedor
Descripcin
Proveedor de
transmisiones por
secuencias

Este proveedor permite exponer tipos de datos de objetos binarios grandes usando
WCF Data Services . Si implementa la interfaz IDataServiceStreamProvider, se crea un
proveedor de transmisiones por secuencias. Este proveedor se puede implementar
junto con cualquier proveedor de orgenes de datos.

4.2.1. Proveedor de Entity Framework


Al igual que ocurre con WCF Data Services , ADO.NET Entity Framework est basado en Entity Data Model,
que es un tipo de modelo entidad-relacin. Entity Framework traduce las operaciones efectuadas sobre su
implementacin de Entity Data Model, que se denomina el modelo conceptual, en operaciones equivalentes
sobre un origen de datos. De esta forma, Entity Framework se convierte en un proveedor ideal para los
servicios de datos basados en datos relacionales y se puede usar cualquier base de datos con un proveedor
de datos que admita Entity Framework con WCF Data Services .
En un modelo conceptual, el contenedor de entidades es la raz del servicio. Debe definir un modelo
conceptual en Entity Framework antes de que un servicio de datos pueda exponer los datos.
WCF Data Services admite el modelo de simultaneidad optimista al permitirle definir un token de
simultaneidad para una entidad. El servicio de datos utiliza este token de simultaneidad, que incluye una o
ms propiedades de la entidad, para determinar si se ha producido un cambio en los datos que se solicitan,
que se estn actualizando o eliminando. Cuando los valores de token obtenidos de la eTag de la solicitud
difieren de los valores actuales de la entidad, el servicio de datos inicia una excepcin. Para indicar que una
propiedad forma parte del token de simultaneidad, debe aplicar el atributo ConcurrencyMode="Fixed" en
el modelo de datos definido por el proveedor de Entity Framework . El token de simultaneidad no puede
incluir ninguna propiedad clave ni de navegacin.

4.2.1.1. Cmo: Crear un servicio de datos mediante un origen de


datos de ADO.NET Entity Framework

MCT: Luis Dueas

Pag 23 de 128

WCF Data Service


WCF Data Services expone los datos de entidad como servicio de datos. ADO.NET Entity Framework
proporciona estos datos de entidad cuando el origen de datos es una base de datos relacional. En este
tema se muestra cmo crear un modelo de datos basado en Entity Framework en una aplicacin web de
Visual Studio que est basada en una base de datos existente y cmo usar este modelo de datos para crear
un nuevo servicio de datos.
Entity Framework tambin proporciona una herramienta de lnea de comandos que puede generar un
modelo de Entity Framework fuera de un proyecto de Visual Studio.

Para agregar un modelo de Entity Framework que est basado en una base de
datos existente a una aplicacin web existente
1.
2.
3.

En el men Proyecto, haga clic en Agregar nuevo elemento.


En el recuadro Plantillas, haga clic en la categora Datos y, a continuacin, seleccione ADO.NET
Entity Data Model.
Escriba el nombre del modelo y, a continuacin, haga clic en Agregar.
Se muestra la primera pgina del Asistente para Entity Data Model.

4.
5.
6.

En el cuadro de dilogo Elegir contenido del modelo, seleccione Generar desde la base de
datos. Despus, haga clic en Siguiente.
Haga clic en el botn Nueva conexin.
En el cuadro de dilogo Propiedades de la conexin, escriba el nombre del servidor, seleccione el
mtodo de autenticacin, escriba el nombre de la base de datos y, a continuacin, haga clic en
Aceptar.
El cuadro de dilogo Elegir la conexin de datos se actualiza con la configuracin de la conexin
de la base de datos.

7.
8.

Asegrese de que est activada la casilla Guardar configuracin de conexin de la entidad en


App.Config como. Despus, haga clic en Siguiente.
En el cuadro de dilogo Elija los objetos de base de datos, seleccione todos los objetos de base
de datos que piensa exponer en el servicio de datos.
Nota:
El servicio de datos no expone automticamente los objetos incluidos en el modelo de datos. El
propio servicio debe exponerlos explcitamente.

9.

Haga clic en Finalizar para completar el asistente.


Con esto se crea un modelo de datos predeterminado basado en una base de datos especfica.
Entity Framework permite personalizar el modelo de datos.

Para crear el servicio de datos usando el nuevo modelo de datos


1.
2.
3.
4.
5.

En Visual Studio, abra el archivo .edmx que representa el modelo de datos.


En el Explorador de modelos, haga clic con el botn secundario en el modelo, haga clic en
Propiedades y, a continuacin, anote el nombre del contenedor de entidades.
En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, seleccione Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione Servicio de datos de ADO.NET.
Proporcione un nombre para el servicio y, a continuacin, haga clic en Aceptar.
Visual Studio crea los archivos de cdigo y marcado XML para el nuevo servicio. De forma
predeterminada, se abre la ventana del editor de cdigo.

MCT: Luis Dueas

Pag 24 de 128

WCF Data Service


6.

En el cdigo para el servicio de datos, reemplace el comentario /* TODO: put your data source

7.

class name here */ de la definicin de la clase que define el servicio de datos por el tipo que
hereda de la clase ObjectContext y que es el contenedor de entidades del modelo de datos, que
anot en el paso 2.
En el cdigo del servicio de datos, permita a los clientes autorizados tener acceso a los conjuntos
de entidades que expone el servicio de datos.
Para probar el servicio de datos Northwind.svc usando un explorador web, siga las instrucciones del
tema Obtener acceso al servicio desde un explorador web (Tutorial rpido de WCF Data Services).

8.

4.2.2. Proveedor de reflexin


Adems de exponer los datos de un modelo de datos a travs de Entity Framework, WCF Data Services
puede exponer los datos que no estn definidos estrictamente en un modelo basado en entidad. El
proveedor de reflexin expone los datos en clases que devuelven tipos que implementan la interfaz
IQueryable. WCF Data Services usa la reflexin con el fin de deducir un modelo de datos para estas clases y
puede convertir las consultas basadas en direcciones realizadas en recursos en consultas basadas en el
lenguaje de consulta integrado (LINQ) realizadas en los tipos IQueryable expuestos.
Nota:
Puede utilizar el mtodo AsQueryable para devolver una interfaz de IQueryable de cualquier clase que
implemente la interfaz de IEnumerable. Esto permite usar tipos de coleccin ms genricos como origen de
datos para un servicio de datos.
El proveedor de reflexin admite las jerarquas de tipos.

Deducir el modelo de datos


Al crear el servicio de datos, el proveedor deduce el modelo de datos por medio de la reflexin. En la lista
siguiente se muestra cmo el proveedor de reflexin deduce el modelo de datos:
Contenedor de entidades: clase que expone los datos como propiedades que devuelven una
instancia de IQueryable. Al direccionar un modelo de datos basado en reflexin, el contenedor de
entidades representa la raz del servicio. Solo se admite una clase de contenedor de entidades para
un espacio de nombres determinado.
Conjuntos de entidades: las propiedades que devuelven instancias de IQueryable se tratan como
conjuntos de entidades. Los conjuntos de entidades se direccionan directamente como recursos en
la consulta. Solo una propiedad del contenedor de entidades puede devolver una instancia de
IQueryable de un tipo determinado.
Tipos de entidad: el tipo T del IQueryable que devuelve el tipo de entidad. El proveedor de
reflexin convierte las clases que forman parte de una jerarqua de herencia en una jerarqua de
tipos de entidad equivalente.
Claves de entidad: cada clase de datos que es un tipo de entidad debe tener una propiedad clave.
Esta propiedad recibe el atributo DataServiceKeyAttribute ([DataServiceKeyAttribute]).
Nota:
Solo debe aplicar el atributo DataServiceKeyAttribute a una propiedad que se pueda usar para
identificar una instancia de forma nica del tipo de entidad. Este atributo se ignora cuando se
aplica a una propiedad de navegacin.
Propiedades de tipo de entidad: aparte de la clave de entidad, el proveedor de reflexin trata las
propiedades accesibles no de indizador de una clase que no sea un tipo de entidad como se
explica a continuacin:

MCT: Luis Dueas

Pag 25 de 128

WCF Data Service


o

Si la propiedad devuelve un tipo primitivo, se supone que es una propiedad de un tipo de


entidad.

Si la propiedad devuelve un tipo que tambin es un tipo de entidad, se supone que es una
propiedad de navegacin que representa el extremo "uno" de una relacin varios a uno o
uno a uno.

Si la propiedad devuelve un IEnumerable de un tipo de entidad, se supone que es una


propiedad de navegacin que representa el extremo "varios" de una relacin uno a uno o
varios a varios.

Si el tipo devuelto de la propiedad es un tipo de valor, la propiedad representa un tipo


complejo.

Nota:
A diferencia de un modelo de datos que est basado en el modelo de entidad-relacin, los modelos que
estn basados en el proveedor de reflexin no entienden los datos relacionales. Debe usar Entity Framework
para exponer los datos relacionales a travs de WCF Data Services .

Asignacin de tipos de datos


Cuando un modelo de datos se deduce de las clases de .NET Framework, los tipos primitivos del modelo se
asignan a los tipos de datos de .NET Framework de la siguiente forma:
Tipo de datos de .NET Framework Tipo del modelo de datos
Byte []

Edm.Binary

Boolean

Edm.Boolean

Byte

Edm.Byte

DateTime

Edm.DateTime

Decimal

Edm.Decimal

Double

Edm.Double

Guid

Edm.Guid

Int16

Edm.Int16

Int32

Edm.Int32

Int64

Edm.Int64

SByte

Edm.SByte

Single

Edm.Single

String

Edm.String

Nota:
Los tipos de valor NULL de .NET Framework se asignan a los mismo tipos del modelo de datos que los tipos
de valor correspondientes a los que no se puede asignar un valor NULL.

Habilitar las actualizaciones en el modelo de datos


Para permitir las actualizaciones de los datos que se exponen a travs de este tipo de modelo de datos, el
proveedor de reflexin define una interfaz IUpdatable. Esta interfaz indica al servicio de datos cmo
conservar las actualizaciones de los tipos expuestos. Para permitir las actualizaciones de los recursos que
define el modelo de datos, la clase de contenedor de entidades debe implementar la interfaz de
IUpdatable.
La interfaz IUpdatable necesita la implementacin de los siguientes miembros para que las actualizaciones
puedan propagarse al origen de datos por medio del proveedor de reflexin:
Miembro
Descripcin
AddReferenceToCollection

Proporciona la funcionalidad para agregar un objeto a una coleccin de


objetos relacionados a los que se tiene acceso desde una propiedad de
navegacin.

ClearChanges

Proporciona la funcionalidad que cancela los cambios pendientes de los

MCT: Luis Dueas

Pag 26 de 128

WCF Data Service


datos.
CreateResource

Proporciona la funcionalidad para crear un recurso nuevo en el


contenedor especificado.

DeleteResource

Proporciona la funcionalidad para eliminar un recurso.

GetResource

Proporciona la funcionalidad para recuperar un recurso que se identifica


por una consulta y un nombre de tipo concretos.

GetValue

Proporciona la funcionalidad para devolver el valor de una propiedad de


un recurso.

Proporciona la funcionalidad para quitar un objeto de una coleccin de


RemoveReferenceFromCollection objetos relacionados a los que se tiene acceso desde una propiedad de
navegacin.
ResetResource

Proporciona la funcionalidad para actualizar un recurso especificado.

ResolveResource

Proporciona la funcionalidad para devolver el recurso que se representa


por una instancia de objeto concreta.

SaveChanges

Proporciona la funcionalidad para guardar todos los cambios pendientes.

SetReference

Proporciona la funcionalidad para establecer una referencia a objeto


relacionada mediante una propiedad de navegacin.

SetValue

Proporciona la funcionalidad para establecer el valor de la propiedad de


un recurso.

Administrar la simultaneidad
WCF Data Services admite un modelo de la simultaneidad optimista al permitirle definir un token de
simultaneidad para una entidad. El servicio de datos utiliza este token de simultaneidad, que incluye una o
ms propiedades de la entidad, para determinar si se ha producido un cambio en los datos que se solicitan,
que se estn actualizando o eliminando. Cuando los valores de token obtenidos de la eTag de la solicitud
difieren de los valores actuales de la entidad, el servicio de datos inicia una excepcin. ETagAttribute se
aplica a un tipo de entidad para definir un token de simultaneidad en el proveedor de reflexin. El token de
simultaneidad no puede incluir ninguna propiedad clave ni de navegacin.

Usar LINQ to SQL con el proveedor de reflexin


Dado que Entity Framework se admite nativamente de forma predeterminada, es el proveedor de datos
recomendado para usar datos relacionales con WCF Data Services . Sin embargo, puede usar el proveedor
de reflexin para usar las clases LINQ to SQL con un servicio de datos. Los conjuntos de resultados Table
que devuelven los mtodos en el DataContext generado por el Object Relational Designer del LINQ to SQL
implementan la interfaz IQueryable. Esto permite que el proveedor de reflexin tenga acceso a estos
mtodos y datos de entidades devueltos en SQL Server utilizando las clases LINQ to SQL generadas. Sin
embargo, dado que LINQ to SQL no implementa la interfaz de IUpdatable, necesita agregar una clase
parcial que extiende la clase parcial existente DataContext para agregar la implementacin IUpdatable.

4.2.2.1. Cmo: Crear un servicio de datos mediante el proveedor de


reflexin
WCF Data Services le permite definir un modelo de datos que est basado en clases arbitrarias siempre que
dichas clases se expongan como objetos que implementan la interfaz IQueryable.

Ejemplo
En el ejemplo siguiente se define un modelo de datos que incluye Items y Orders. La clase del contenedor
de entidades OrderItemData tiene dos mtodos pblicos que devuelven interfaces IQueryable. Estas
interfaces son los conjuntos de entidades de los tipos de entidad Items y Orders. Cada Order puede incluir
varios Items, por lo que el tipo de entidad Orders tiene una propiedad de navegacin Items que devuelve
una coleccin de objetos Items. La clase del contenedor de entidades OrderItemData es el tipo genrico de
la clase DataService de la que se deriva el servicio de datos OrderItems.

MCT: Luis Dueas

Pag 27 de 128

WCF Data Service


Nota:
Dado que este ejemplo muestra un proveedor de datos en memoria y los cambios no se conservan fuera de
las instancias de objeto actuales, no hay ninguna ventaja derivada de implementar la interfaz IUpdatable.
Imports System
Imports System.Collections.Generic
Imports System.Data.Services
Imports System.Data.Services.Common
Imports System.Linq
Namespace CustomDataServiceClient
<DataServiceKeyAttribute("OrderId")> _
Public Class Order
Private _orderId As Integer
Private _customer As String
Private _items As IList(Of Item)
Public Property OrderId() As Integer
Get
Return _orderId
End Get
Set(ByVal value As Integer)
_orderId = value
End Set
End Property
Public Property Customer() As String
Get
Return _customer
End Get
Set(ByVal value As String)
_customer = value
End Set
End Property
Public Property Items() As IList(Of Item)
Get
Return _items
End Get
Set(ByVal value As IList(Of Item))
_items = value
End Set
End Property
End Class
<EntityPropertyMappingAttribute("Product", "productname", _
"orders", "http://schema.examples.microsoft.com/dataservices", True)> _
<DataServiceKeyAttribute("Product")> _
Public Class Item
Private _product As String
Private _quantity As Integer
Public Property Product() As String
Get
Return _product
End Get
Set(ByVal value As String)
_product = value
End Set

MCT: Luis Dueas

Pag 28 de 128

WCF Data Service


End Property
Public Property Quantity() As Integer
Get
Return _quantity
End Get
Set(ByVal value As Integer)
_quantity = value
End Set
End Property
End Class
Partial Public Class OrderItemData
#Region "Populate Service Data"
Shared _orders As IList(Of Order)
Shared _items As IList(Of Item)
Sub New()
_orders = New Order() { _
New Order() With {.OrderId = 0, .Customer = "Peter Franken", .Items = New List(Of Item)()}, _
New Order() With {.OrderId = 1, .Customer = "Ana Trujillo", .Items = New List(Of Item)()}}
_items = New Item() { _
New Item() With {.Product = "Chai", .Quantity = 10}, _
New Item() With {.Product = "Chang", .Quantity = 25}, _
New Item() With {.Product = "Aniseed Syrup", .Quantity = 5}, _
New Item() With {.Product = "Chef Anton's Cajun Seasoning", .Quantity = 30}}
_orders(0).Items.Add(_items(0))
_orders(0).Items.Add(_items(1))
_orders(1).Items.Add(_items(2))
_orders(1).Items.Add(_items(3))
End Sub
#End Region
Public ReadOnly Property Orders() As IQueryable(Of Order)
Get
Return _orders.AsQueryable()
End Get
End Property
Public ReadOnly Property Items() As IQueryable(Of Item)
Get
Return _items.AsQueryable()
End Get
End Property
End Class
Public Class OrderItems
Inherits DataService(Of OrderItemData)
' This method is called only once to initialize
' service-wide policies.
Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
config.SetEntitySetAccessRule("Orders", EntitySetRights.All)
config.SetEntitySetAccessRule("Items", EntitySetRights.All)
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2
End Sub
End Class
End Namespace

MCT: Luis Dueas

Pag 29 de 128

WCF Data Service

4.2.2.2. Cmo: Crear un servicio de datos mediante un origen de


datos LINQ to SQL
WCF Data Services expone los datos de entidad como servicio de datos. El proveedor de reflexin le permite
definir un modelo de datos que est basado en cualquier clase que exponga miembros que devuelvan una
implementacin de IQueryable. Para poder realizar actualizaciones en los datos del origen de datos, estas
clases tambin deben implementar la interfaz IUpdatable. En este tema se muestra cmo crear clases LINQ
to SQL que tienen acceso a la base de datos de ejemplo Northwind usando el proveedor de reflexin, as
como el modo de crear el servicio de datos que est basado en estas clases de datos.

Para agregar clases LINQ to SQL a un proyecto


1.
2.
3.
4.

En una aplicacin de Visual Basic o de C#, en el men Proyecto, haga clic en Agregar nuevo
elemento.
Haga clic en la plantilla Clases de LINQ to SQL.
Cambie el nombre a Northwind.dbml.
Haga clic en Agregar.
Se agrega al proyecto el archivo Northwind.dbml y se abre Object Relational Designer (O/R
Designer).

5.

En Servidor/Explorador de bases de datos, bajo Northwind, expanda Tablas y arrastre la tabla


Customers a Object Relational Designer (O/R Designer).
Se crea una clase de entidad Customer que aparece en la superficie de diseo.

6.
7.

Repita el paso 6 para las tablas Orders, Order_Details y Products.


Haga clic con el botn secundario en el nuevo archivo .dbml que representa las clases LINQ to SQL
y haga clic en Ver cdigo.
Esto crea una nueva pgina de cdigo subyacente denominada Northwind.cs que contiene una
definicin de clase parcial para la clase que hereda de la clase DataContext, que en este caso es
NorthwindDataContext.

8.

Reemplace el contenido del archivo de cdigo Northwind.cs por el cdigo siguiente. Este cdigo
implementa el proveedor de reflexin extendiendo la clase DataContext y las clases de datos
generadas por LINQ to SQL:
Imports System.ComponentModel
Imports System.Collections
Imports System.Linq
Imports System.Reflection
Imports System.Data.Linq
Imports System.Data.Linq.Mapping
Imports System.Data.Services
Imports System.Data.Services.Common
' Define the key properties for the LINQ to SQL data classes.
<DataServiceKeyAttribute("CustomerID")> _
Partial Public Class Customer
End Class
<DataServiceKeyAttribute("ProductID")> _
Partial Public Class Product
End Class
<DataServiceKeyAttribute("OrderID")> _
Partial Public Class Order
End Class

MCT: Luis Dueas

Pag 30 de 128

WCF Data Service


<DataServiceKeyAttribute("OrderID", "ProductID")> _
Partial Public Class Order_Detail
End Class
#Region "IUpdatable implementation"
' Define the IUpdatable implementation for LINQ to SQL.
Partial Public Class NorthwindDataContext
Implements IUpdatable
' Creates an object in the container.
Function CreateResource(ByVal containerName As String, ByVal fullTypeName As String) _
As Object Implements IUpdatable.CreateResource
Dim t = Type.GetType(fullTypeName, True)
Dim table = GetTable(t)
Dim resource = Activator.CreateInstance(t)
table.InsertOnSubmit(resource)
Return resource
End Function
' Gets the object referenced by the resource.
Function GetResource(ByVal query As IQueryable, ByVal fullTypeName As String) As Object _
Implements IUpdatable.GetResource
Dim resource = query.Cast(Of Object)().SingleOrDefault()
' fullTypeName can be null for deletes
If fullTypeName IsNot Nothing AndAlso resource.GetType().FullName <> fullTypeName Then
Throw New ApplicationException("Unexpected type for this resource.")
End If
Return resource
End Function
' Resets the value of the object to its default value.
Function ResetResource(ByVal resource As Object) As Object _
Implements IUpdatable.ResetResource
Dim t = resource.GetType()
Dim table = Mapping.GetTable(t)
Dim dummyResource = Activator.CreateInstance(t)
For Each member In table.RowType.DataMembers
If Not member.IsPrimaryKey AndAlso Not member.IsDeferred AndAlso _
Not member.IsAssociation AndAlso Not member.IsDbGenerated Then
Dim defaultValue = member.MemberAccessor.GetBoxedValue(dummyResource)
member.MemberAccessor.SetBoxedValue(resource, defaultValue)
End If
Next
Return resource
End Function
' Sets the value of the given property on the object.
Sub SetValue(ByVal targetResource As Object, ByVal propertyName As String, _
ByVal propertyValue As Object) Implements IUpdatable.SetValue
Dim table = Mapping.GetTable(targetResource.GetType())
Dim member = table.RowType.DataMembers.Single(Function(x) x.Name = propertyName)
member.MemberAccessor.SetBoxedValue(targetResource, propertyValue)
End Sub
' Gets the value of a property on an object.
Function GetValue(ByVal targetResource As Object, ByVal propertyName As String) _
As Object Implements IUpdatable.GetValue
Dim table = Mapping.GetTable(targetResource.GetType())

MCT: Luis Dueas

Pag 31 de 128

WCF Data Service


Dim member = _
table.RowType.DataMembers.Single(Function(x) x.Name = propertyName)
Return member.MemberAccessor.GetBoxedValue(targetResource)
End Function
' Sets the related object for a reference.
Sub SetReference(ByVal targetResource As Object, ByVal propertyName As String, _
ByVal propertyValue As Object) Implements IUpdatable.SetReference
CType(Me, IUpdatable).SetValue(targetResource, propertyName, propertyValue)
End Sub
' Adds the object to the related objects collection.
Sub AddReferenceToCollection(ByVal targetResource As Object, ByVal propertyName As String, _
ByVal resourceToBeAdded As Object) _
Implements IUpdatable.AddReferenceToCollection
Dim pi = targetResource.GetType().GetProperty(propertyName)
If pi Is Nothing Then
Throw New Exception("Can't find property")
End If
Dim collection = CType(pi.GetValue(targetResource, Nothing), IList)
collection.Add(resourceToBeAdded)
End Sub
' Removes the object from the related objects collection.
Sub RemoveReferenceFromCollection(ByVal targetResource As Object, ByVal propertyName As String, _
ByVal resourceToBeRemoved As Object) _
Implements IUpdatable.RemoveReferenceFromCollection
Dim pi = targetResource.GetType().GetProperty(propertyName)
If pi Is Nothing Then
Throw New Exception("Can't find property")
End If
Dim collection = CType(pi.GetValue(targetResource, Nothing), IList)
collection.Remove(resourceToBeRemoved)
End Sub
' Deletes the resource.
Sub DeleteResource(ByVal targetResource As Object) _
Implements IUpdatable.DeleteResource
Dim table = GetTable(targetResource.GetType())
table.DeleteOnSubmit(targetResource)
End Sub
' Saves all the pending changes.
Sub SaveChanges() Implements IUpdatable.SaveChanges
SubmitChanges()
End Sub
' Returns the actual instance of the resource represented
' by the resource object.
Function ResolveResource(ByVal resource As Object) As Object Implements IUpdatable.ResolveResource
Return resource
End Function
' Reverts all the pending changes.
Sub ClearChanges() Implements IUpdatable.ClearChanges
' Raise an exception as there is no real way to do this with LINQ to SQL.
' Comment out the following line if you'd prefer a silent failure
Throw New NotSupportedException()
End Sub

MCT: Luis Dueas

Pag 32 de 128

WCF Data Service


End Class
#End Region

Para crear un servicio de datos usando un modelo de datos basado en LINQ to


SQL
1.
2.
3.

En el Explorador de soluciones, haga clic con el botn secundario en el nombre del proyecto de
ASP.NET y, a continuacin, haga clic en Agregar nuevo elemento.
En el cuadro de dilogo Agregar nuevo elemento, seleccione WCF Data Service.
Proporcione un nombre para el servicio y, a continuacin, haga clic en Aceptar.
Visual Studio crea los archivos de cdigo y marcado XML para el nuevo servicio. De forma
predeterminada, se abre la ventana del editor de cdigo.

4.

En el cdigo para el servicio de datos, reemplace el comentario /* TODO: put your data source

5.

class name here */ de la definicin de la clase que define el servicio de datos por el tipo que es el
contenedor de entidades del modelo de datos, que en este caso es NorthwindDataContext.
En el cdigo del servicio de datos, reemplace el cdigo de marcador de posicin de la funcin
InitializeService por el siguiente:
config.SetEntitySetAccessRule("Customers", EntitySetRights.ReadMultiple)
config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead _
Or EntitySetRights.WriteMerge)
config.SetEntitySetAccessRule("Order_Details", EntitySetRights.AllRead _
Or EntitySetRights.AllWrite)
config.SetEntitySetAccessRule("Products", EntitySetRights.ReadMultiple)

Esto permite a los clientes autorizados tener acceso a los recursos para los tres conjuntos de
entidades especificados.
6.

Para probar el servicio de datos Northwind.svc usando un explorador web, siga las instrucciones del
tema Obtener acceso al servicio desde un explorador web.

4.2.3. Proveedores de servicios de datos personalizados


WCF Data Services incluye un conjunto de proveedores que permite definir un modelo de datos basado en
tipos de datos enlazados en tiempo de ejecucin.
Proveedor

Descripcin

Proveedor de
metadatos

Este es el proveedor principal de servicios de datos personalizados que permite definir


un modelo de datos personalizado en tiempo de ejecucin implementando la interfaz
IDataServiceMetadataProvider.

Proveedor de
consultas

Este proveedor permite ejecutar las consultas sobre un modelo de datos personalizado
que se define utilizando la interfaz IDataServiceMetadataProvider. El proveedor de
consultas se crea implementando la interfaz IDataServiceQueryProvider.

Proveedor de
actualizaciones

Este proveedor permite realizar actualizaciones a los tipos expuestos en un proveedor


de servicio de datos personalizado y administrar la simultaneidad. El proveedor de
actualizaciones se crea implementando la interfaz IDataServiceUpdateProvider.

Proveedor de
paginaciones

Este proveedor se utiliza con el proveedor del servicio de datos personalizado para
habilitar la compatibilidad con la paginacin controlada por servidor. Un proveedor de
paginaciones para un servicio de datos personalizado se crea implementando la interfaz
IDataServicePagingProvider.

Proveedor de
transmisiones por
secuencias

Este proveedor permite exponer tipos de datos de objetos binarios grandes como una
secuencia. Si implementa la interfaz IDataServiceStreamProvider, se crea un proveedor
de transmisiones por secuencias. El proveedor de transmisiones por secuencias tambin

MCT: Luis Dueas

Pag 33 de 128

WCF Data Service


se puede utilizar con Entity Framework y proveedores de orgenes de datos de
reflexin.

4.2.4. Proveedores de transmisin por secuencias


Un servicio de datos puede exponer datos binarios de objetos grandes. Estos datos binarios pueden
representar secuencias de vdeo y audio, imgenes, archivos de documento u otros tipos de medios
binarios. Cuando una entidad del modelo de datos incluye una o ms propiedades binarias, el servicio de
datos devuelve estos datos binarios codificados en base 64 en la entrada de la fuente de respuesta. Dado
que la carga y la serializacin de datos binarios grandes de esta manera pueden afectar al rendimiento,
Open Data Protocol (OData) define un mecanismo para recuperar datos binarios independientemente de la
entidad a la que pertenezcan. Para ello, se separan los datos binarios de la entidad en uno o varios flujos de
datos.
Recurso multimedia: los datos binarios que pertenecen a una entidad, como vdeo, audio, imagen u
otro tipo de flujo de recursos multimedia.
Entrada de vnculo multimedia: entidad con una referencia a un flujo de recursos multimedia
relacionado.
Con WCF Data Services , defina un flujo de recursos binarios implementando un proveedor de transmisin
de datos por secuencias. La implementacin del proveedor de transmisin por secuencias proporciona al
servicio de datos la secuencia de recursos multimedia asociada con una entidad concreta como objeto
Stream. Esta implementacin permite que el servicio de datos acepte y devuelva los recursos multimedia a
travs del protocolo HTTP como flujos de datos binarios de un tipo MIME especificado.
La configuracin de un servicio de datos para que admita la transmisin por secuencias de datos binarios
requiere los siguientes pasos:
1.

Atribuya una o ms entidades del modelo de datos como una entrada de vnculo multimedia. Estas
entidades no deben incluir los datos binarios que se van a transmitir por secuencias. Las
propiedades binarias de una entidad siempre se devuelven en la entrada como datos binarios
codificados en base 64.

2.

Implemente la interfaz T:System.Data.Services.Providers.IDataServiceStreamProvider.

3.

Defina un servicio de datos que implemente la interfaz IServiceProvider. El servicio de datos usa la
implementacin del mtodo GetService para acceder a la implementacin del proveedor de
transmisin de datos por secuencias. Este mtodo devuelve la implementacin del proveedor de
transmisin por secuencias adecuado.

4.

Habilite flujos de mensajes grandes en la configuracin de la aplicacin web.

5.

Habilite el acceso a los recursos binarios en el servidor o en un origen de datos.

Los ejemplos de este tema se basan en un servicio de fotografas de transmisin por secuencias de ejemplo,
que se describe con todo detalle en la entrada del blog relacionado con la parte 1 de la implementacin de
un proveedor de transmisin por secuencias de la serie de proveedores de transmisin por secuencias de
servicios de datos.

Definir una entrada de vnculo multimedia en el modelo de datos


El proveedor del origen de datos determina cmo se define una entidad como entrada de vnculo
multimedia en el modelo de datos.
Proveedor de Entity Framework
Para indicar que una entidad es una entrada de vnculo multimedia, agregue el atributo HasStream
a la definicin del tipo de entidad en el modelo conceptual, como en el siguiente ejemplo:
<EntityType xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"

MCT: Luis Dueas

Pag 34 de 128

WCF Data Service


Name="PhotoInfo" m:HasStream="true">
<Key>
<PropertyRef Name="PhotoId" />
</Key>
<Property Name="PhotoId" Type="Int32" Nullable="false"
annotation:StoreGeneratedPattern="Identity" />
<Property Name="FileName" Type="String" Nullable="false" />
<Property Name="FileSize" Type="Int32" Nullable="true" />
<Property Name="DateTaken" Type="DateTime" Nullable="true" />
<Property Name="TakenBy" Type="String" Nullable="true" />
<Property Name="DateAdded" Type="DateTime" Nullable="false" />
<Property Name="Exposure" Type="PhotoData.Exposure" Nullable="false" />
<Property Name="Dimensions" Type="PhotoData.Dimensions" Nullable="false" />
<Property Name="DateModified" Type="DateTime" Nullable="false" />
<Property Name="Comments" Type="String" MaxLength="Max"
FixedLength="false" Unicode="true" />
<Property Name="ContentType" Type="String" MaxLength="50" FixedLength="false" Unicode="true" />
</EntityType>

Tambin debe agregar el espacio de nombres

xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata a la entidad o a la
raz del archivo .edmx o del archivo .csdl que definen el modelo de datos.
Proveedor de reflexin
Para indicar que una entidad es una entrada de vnculo multimedia, agregue el atributo
HasStreamAttribute a la clase que define el tipo de entidad en el proveedor de reflexin.
Proveedor de servicios de datos personalizados
Cuando se usan proveedores de servicios personalizados, implemente la interfaz
IDataServiceMetadataProvider para definir los metadatos del servicio de datos. Indique que un flujo
de recurso binario pertenezca a la clase ResourceType estableciendo el valor de la propiedad
IsMediaLinkEntry en true en la clase ResourceType que representa el tipo de entidad, que es una
entrada de vnculo multimedia.

Implementar la interfaz IDataServiceStreamProvider


Para crear un servicio de datos que admita flujos de datos binarios, debe implementar la interfaz
IDataServiceStreamProvider. Esta implementacin habilita el servicio de datos para devolver al cliente datos
binarios como flujo y utilizar los datos binarios como flujo enviado desde el cliente. El servicio de datos crea
una instancia de esta interfaz cuando sea necesario para acceder a los datos binarios como flujo. La interfaz
IDataServiceStreamProvider especifica los siguientes miembros:
Nombre del miembro
Descripcin

DeleteStream

El servicio de datos invoca este mtodo para eliminar el recurso multimedia


correspondiente cuando se elimina su entrada de vnculo multimedia. Cuando se
implementa IDataServiceStreamProvider, este mtodo contiene el cdigo que
elimina el recurso multimedia asociado con la entrada de vnculo multimedia
proporcionada.

GetReadStream

El servicio de datos invoca este mtodo para devolver un recurso multimedia como
un flujo. Cuando se implementa IDataServiceStreamProvider, este mtodo
contiene el cdigo que proporciona un flujo que el servicio de datos utiliza para
devolver el recurso multimedia que est asociado a la entrada de vnculo
multimedia proporcionada.

GetReadStreamUri

El servicio de datos invoca este mtodo para devolver el URI que se utiliza para
solicitar el recurso multimedia de la entrada de vnculo multimedia. Este valor se usa
para crear el atributo src en el elemento de contenido de la entrada de vnculo
multimedia que se utiliza para solicitar el flujo de datos. Cuando este mtodo
devuelve null, el servicio de datos automticamente determina el URI. Use este

MCT: Luis Dueas

Pag 35 de 128

WCF Data Service


mtodo cuando deba proporcionar clientes con acceso directo a datos binarios sin
usar el proveedor de flujos.
GetStreamContentType

El servicio de datos invoca este mtodo para devolver el valor Content-Type del
recurso multimedia asociado con la entrada de vnculo multimedia especificada.

GetStreamETag

El servicio de datos invoca este mtodo para devolver el objeto eTag del flujo de
datos que est asociado con la entidad especificada. Este mtodo se utiliza cuando
se administra la simultaneidad de los datos binarios. Cuando este mtodo devuelve
null, el servicio de datos no realiza el seguimiento de la simultaneidad.

GetWriteStream

El servicio de datos invoca este mtodo para obtener el flujo que se utiliza cuando
se recibe el flujo enviado desde el cliente. Cuando implemente la interfaz
IDataServiceStreamProvider, debe devolver un flujo grabable en el que el servicio
de datos pueda escribir los datos del flujo recibidos.

ResolveType

Devuelve un nombre de tipo calificado con el espacio de nombres que representa el


tipo que el motor en tiempo de ejecucin del servicio de datos debe crear para la
entrada de vnculo multimedia asociada al flujo de datos del recurso multimedia que
se est insertando.

Crear el servicio de transmisin de datos por secuencias


Para proporcionar al motor de tiempo de ejecucin de WCF Data Services acceso a la implementacin de la
interfaz IDataServiceStreamProvider, el servicio de datos que cree tambin debe implementar la interfaz
IServiceProvider. En el siguiente ejemplo se muestra cmo implementar el mtodo GetService para
devolver una instancia de la clase

PhotoServiceStreamProvider que implemente la interfaz

IDataServiceStreamProvider.
Partial Public Class PhotoData
Inherits DataService(Of PhotoDataContainer)
Implements IServiceProvider
' This method is called only once to initialize service-wide policies.
Public Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
config.SetEntitySetAccessRule("PhotoInfo", _
EntitySetRights.ReadMultiple Or _
EntitySetRights.ReadSingle Or _
EntitySetRights.AllWrite)
' Named streams require version 3 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3
End Sub
#Region "IServiceProvider Members"
Public Function GetService(ByVal serviceType As Type) As Object _
Implements IServiceProvider.GetService
If serviceType Is GetType(IDataServiceStreamProvider) _
Or serviceType Is GetType(IDataServiceStreamProvider2) Then
Return New PhotoServiceStreamProvider(Me.CurrentDataSource)
End If
Return Nothing
End Function
#End Region
End Class

Habilitar flujos binarios grandes en el entorno de hospedaje


Cuando cree un servicio de datos en una aplicacin web de ASP.NET, se usa Windows Communication
Foundation (WCF) para proporcionar la implementacin del protocolo HTTP. De forma predeterminada,
WCF limita el tamao de los mensajes HTTP a solo 65K bytes. Para poder transmitir datos binarios grandes
por secuencias al servicio de datos y desde l, debe configurar tambin la aplicacin web para habilitar

MCT: Luis Dueas

Pag 36 de 128

WCF Data Service


archivos binarios grandes y utilizar secuencias para la transferencia. Para ello, en el elemento <configuration

/> del archivo Web.config de la aplicacin agregue lo siguiente:


<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<!-- The name of the service -->
<service name="PhotoService.PhotoData">
<!--you can leave the address blank or specify your end point URI-->
<endpoint binding="webHttpBinding" bindingConfiguration="higherMessageSize"
contract="System.Data.Services.IRequestHandler"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<!-- configure the maxReceivedMessageSize value to suit the max size of
the request (in bytes) you want the service to receive-->
<binding name="higherMessageSize" transferMode="Streamed"
maxReceivedMessageSize="2147483647"/>
</webHttpBinding>
</bindings>
</system.serviceModel>

Nota:
Debe usar un modo de transferencia del campo System.ServiceModel.TransferMode.Streamed para
asegurarse de que los datos binarios en los mensajes de solicitud y respuesta se transfieran y que WCF no
los almacene en bfer.
De forma predeterminada, Internet Information Services (IIS) tambin limita el tamao de las respuestas a 4
MB. Para habilitar el servicio de datos con el fin de recibir flujos mayores que 4 MB cuando se ejecute en IIS,
tambin debe establecer el atributo maxRequestLength del elemento httpRuntime Element de la seccin
de configuracin de <system.web /> como se muestra en el siguiente ejemplo:
<system.web>
<!-- maxRequestLength (in KB): default=4000 (4MB); max size=2048MB. -->
<httpRuntime maxRequestLength="2000000"/>
</system.web>

Usar flujos de datos en una aplicacin cliente


La biblioteca cliente de WCF Data Services le permite recuperar y actualizar estos recursos expuestos como
flujos binarios en el cliente.

Consideraciones para trabajar con un proveedor de transmisin por secuencias


A continuacin se enumeran algunas de las consideraciones que debe tener en cuenta al implementar un
proveedor de transmisiones por secuencias y al tener acceso a los recursos multimedia de un servicio de
datos.
Los recursos multimedia no admiten solicitudes MERGE. Utilice una solicitud PUT para cambiar el
recurso multimedia de una entidad existente.
Una solicitud POST no se puede utilizar para crear una entrada de vnculo multimedia. En su lugar,
debe emitir una solicitud POST para crear un nuevo recurso multimedia y el servicio de datos crear
una entrada de vnculo multimedia con los valores predeterminados. Una solicitud MERGE o PUT
posterior puede actualizar esta nueva entidad. Tambin puede considerar la opcin de almacenar
en memoria cach la entidad y realizar actualizaciones en el contenedor de elementos eliminados,
como establecer el valor de propiedad en el valor del encabezado Slug en la solicitud POST.

MCT: Luis Dueas

Pag 37 de 128

WCF Data Service


Cuando se recibe una solicitud POST, el servicio de datos llama a GetWriteStream para crear el
recurso multimedia antes de llamar a SaveChanges para crear la entrada de vnculo multimedia.
Una implementacin de GetWriteStream no debe devolver un objeto MemoryStream. Cuando se
utiliza este tipo de flujo, se producirn problemas de recursos de memoria cuando el servicio reciba
flujos de datos muy grandes.
A continuacin se enumeran algunas de las consideraciones que debe tener en cuenta al almacenar
recursos multimedia en una base de datos:

En el modelo de datos no debe incluirse una propiedad binaria que sea un recurso
multimedia. Todas las propiedades expuestas en un modelo de datos se devuelven en la
entrada de una fuente de respuesta.

Para mejorar el rendimiento con un flujo binario grande, recomendamos crear una clase de
flujo personalizado para almacenar datos binarios en la base de datos. La implementacin
de GetWriteStream devuelve esta clase y enva los datos binarios a la base de datos en
fragmentos. En el caso de una base de datos de SQL Server, se recomienda usar un objeto
FILESTREAM para transmitir los datos por secuencias a la base de datos cuando los datos
binarios ocupen ms de 1 MB.

Asegrese de que la base de datos est diseada para almacenar los flujos binarios
grandes que vaya a recibir el servicio de datos.

Cuando un cliente enva a una solicitud POST para insertar una entrada de vnculo
multimedia con un recurso multimedia en una solicitud nica, se llama a GetWriteStream
para obtener el flujo antes de que el servicio de datos inserte la nueva entidad en la base
de datos. Una implementacin del proveedor de transmisiones por secuencias debe ser
capaz de controlar este comportamiento del servicio de datos. Considere la opcin de usar
una tabla de datos independiente para almacenar los datos binarios o almacenar el flujo
de datos en un archivo hasta que la entidad se haya insertado en la base de datos.

Cuando implemente los mtodos DeleteStream, GetWriteStream o GetReadStream, debe utilizar


el objeto eTag y los valores Content-Type y que se proporcionan como parmetros de mtodo. No
establezca el objeto eTag ni los encabezados Content-Type en la implementacin del proveedor
IDataServiceStreamProvider.
De forma predeterminada, el cliente enva secuencias binarias grandes mediante codificacin de
transferencia HTTP fragmentada. Dado que el servicio de desarrollo de ASP.NET no admite este
tipo de codificacin, no podr usar este servidor web para hospedar los servicios de transmisin de
datos por secuencias que deban aceptar flujos binarios grandes.

4.3. Operaciones de servicio


WCF Data Services le permite definir operaciones de servicio en un servicio de datos para exponer mtodos
del servidor. Las operaciones de servicio se direccionan como los dems recursos del servicio de datos,
mediante los URI. Las operaciones de servicio le permiten exponer la lgica de negocios de un servicio de
datos; por ejemplo, implementar la lgica de validacin, aplicar la seguridad basada en roles o exponer
capacidades de consulta especializadas. Estas operaciones son mtodos agregados a la clase del servicio de
datos derivada de DataService. Como el resto de los recursos del servicio de datos, puede proporcionar
parmetros al mtodo de operacin de servicio. Por ejemplo, el siguiente URI de operacin de servicio
(basado en el servicio de datos del tutorial rpido) pasa el valor London al parmetro city:
http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'

La definicin de esta operacin de servicio es la siguiente:


<WebGet()> _
Public Function GetOrdersByCity(ByVal city As String) As IQueryable(Of Order)

MCT: Luis Dueas

Pag 38 de 128

WCF Data Service


Puede usar la propiedad CurrentDataSource de la clase DataService para tener acceso directo al origen de
datos que est usando el servicio de datos.

Requisitos que deben cumplir las operaciones de servicio


Al definir operaciones de servicio en el servicio de datos deben tenerse en cuenta los requisitos siguientes.
Si un mtodo no los cumple, no se expondr como operacin de servicio para el servicio de datos.
La operacin debe ser un mtodo de instancia pblica que sea miembro de la clase del servicio de
datos.
El mtodo de la operacin solo puede aceptar parmetros de entrada.
Si se definen parmetros, el tipo de cada parmetro debe ser un tipo primitivo.
El mtodo debe devolver uno de los elementos siguientes:

void (Nothing en Visual Basic)

IEnumerable

IQueryable

Un tipo de entidad en el modelo de datos expuesto por el servicio de datos.

Una clase primitiva como entero o cadena.

Para admitir opciones de consulta como ordenaciones, paginaciones y filtrados, los mtodos de las
operaciones de servicio deben devolver IQueryable. Las solicitudes a operaciones de servicio que
incluyen opciones de consulta se rechazan para las operaciones que solo devuelven IEnumerable.
Para que se pueda tener acceso a las entidades relacionadas usando las propiedades de
navegacin, la operacin de servicio debe devolver IQueryable.
El mtodo se debe anotar con el atributo [WebGet] o [WebInvoke].

[WebGet] permite invocar el mtodo usando una solicitud GET.

[WebInvoke] permite invocar el mtodo usando una solicitud POST.

Una operacin de servicio se puede anotar con el elemento SingleResultAttribute que especifica
que el valor devuelto desde el mtodo es una sola entidad en vez de una coleccin de entidades.
Esta distincin dicta la serializacin resultante de la respuesta y la manera en que se representan en
el URI los recorridos de las propiedades de navegacin adicionales. Por ejemplo, cuando use la
serializacin AtomPub, una sola instancia de tipo de recurso se representa como elemento de
entrada y un conjunto de instancias como elemento de fuente.

Direccionar operaciones de servicio


Puede direccionar las operaciones de servicio colocando el nombre del mtodo en el primer segmento de la
ruta de acceso de un URI. Por ejemplo, el URI siguiente tiene acceso a una operacin GetOrdersByCity que
devuelve una coleccin IQueryable de objetos Orders, ordenada en orden descendente por RequiredDate,
junto con los objetos Order_Details relacionados:
http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Details&$orderby=RequiredDate desc

Se pueden agregar segmentos de ruta de acceso u opciones de consulta adicionales al URI en funcin del
tipo de valor devuelto de la operacin de servicio.

MCT: Luis Dueas

Pag 39 de 128

WCF Data Service


Tipos de valor
devueltos vlidos

Reglas que deben cumplir los URI

void (Nothing en
Visual Basic)
O bien
Tipos de entidad

El URI debe ser un solo segmento de ruta de acceso que sea el nombre de la
operacin de servicio. No se permiten las opciones de consulta.

O bien
Tipos primitivos
IEnumerable

El URI debe ser un solo segmento de ruta de acceso que sea el nombre de la
operacin de servicio. Puesto que el tipo de resultado no es un tipo IQueryable, no se
permiten las opciones de consulta.

IQueryable

Se permiten segmentos de ruta de acceso de la consulta adems de la ruta de acceso


que es el nombre de la operacin de servicio. Tambin se permiten las opciones de
consulta.

Control de acceso a las operaciones de servicio


El mtodo SetServiceOperationAccessRule de la clase IDataServiceConfiguration controla la visibilidad en el
mbito de todos los servicios de las operaciones de servicio, de la misma forma que el mtodo
SetEntitySetAccessRule controla la visibilidad del conjunto de entidades. Por ejemplo, la lnea de cdigo
siguiente de la definicin del servicio de datos permite el acceso a la operacin de servicio

CustomersByCity.
config.SetServiceOperationAccessRule("GetOrdersByCity", ServiceOperationRights.AllRead)

Nota:
Si una operacin de servicio tiene un tipo de valor devuelto que se oculta restringiendo el acceso en los
conjuntos de entidades subyacentes, la operacin de servicio no estar disponible para las aplicaciones
cliente.

4.3.1. Cmo: Definir una operacin de servicio


WCF Data Services expone mtodos que se definen en el servidor como operaciones de servicio. Las
operaciones de servicio permiten que un servicio de datos proporcione acceso a travs de un URI a un
mtodo que se define en el servidor. Para definir una operacin de servicio, aplique el atributo WebGet] o
[WebInvoke] al mtodo. Para que admita operadores de consulta, la operacin del servicio debe devolver
una instancia de IQueryable. Las operaciones del servicio pueden tener acceso al origen de datos
subyacente por medio de la propiedad CurrentDataSource en DataService.
En el ejemplo de este tema se define una operacin del servicio denominada GetOrdersByCity que
devuelve una instancia de IQueryable filtrada de los objetos Order_Details y Orders relacionados. En el
ejemplo se obtiene acceso a la instancia de ObjectContext que es el origen de datos del servicio de datos
de ejemplo Northwind. Este servicio se crea cuando se completa el Tutorial rpido de WCF Data Services.

Para definir una operacin del servicio en el servicio de datos Northwind


1.

En el proyecto del servicio de datos Northwind, abra el archivo Northwind.svc.

2.

En la clase Northwind, defina un mtodo de operacin de servicio denominado GetOrdersByCity


como sigue:
<WebGet()> _
Public Function GetOrdersByCity(ByVal city As String) As IQueryable(Of Order)

MCT: Luis Dueas

Pag 40 de 128

WCF Data Service


En el mtodo InitializeService de la clase Northwind, agregue el siguiente cdigo para permitir el

3.

acceso a la operacin del servicio:


config.SetServiceOperationAccessRule("GetOrdersByCity", ServiceOperationRights.AllRead)

Para consultar la operacin del servicio GetOrdersByCity


En un explorador web, escriba uno de los siguientes URI para invocar la operacin del servicio que
se define en el siguiente ejemplo:

http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'

http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$top=2

http://localhost:12345/Northwind.svc/GetOrdersByCity?city='London'&$expand=Order_Detai
ls&$orderby=RequiredDate desc

Ejemplo
En el ejemplo siguiente se implementa una operacin del servicio denominada GetOrderByCity en el
servicio de datos Northwind. Esta operacin utiliza ADO.NET Entity Framework para devolver un conjunto de
objetos Order_Details y Orders relacionados como una instancia de IQueryable basada en el nombre de
ciudad suministrado.
Nota:
Los operadores de consulta se admiten en este extremo de la operacin del servicio porque el mtodo
devuelve una instancia de IQueryable.
<WebGet()> _
Public Function GetOrdersByCity(ByVal city As String) As IQueryable(Of Order)
If String.IsNullOrEmpty(city) Then
Throw New ArgumentNullException("city", _
"You must provide a value for the parameter'city'.")
End If
' Get the ObjectContext that is the data source for the service.
Dim context As NorthwindEntities = Me.CurrentDataSource
Try
Dim selectedOrders = From order In context.Orders.Include("Order_Details") _
Where order.Customer.City = city _
Select order
Return selectedOrders
Catch ex As Exception
Throw New ApplicationException("An error occurred: {0}", ex)
End Try
End Function

4.4. Personalizacin de fuentes


WCF Data Services utiliza Open Data Protocol (OData) para exponer los datos como fuente. OData admite
los formatos Atom y JSON (JavaScript Object Notation) para las fuentes de distribucin de datos. Cuando
usa una fuente Atom, OData proporciona un mtodo estndar para serializar los datos, como entidades y
relaciones, en un formato XML que se puede incluir en el cuerpo de mensaje HTTP. OData define una
asignacin de entidad-propiedad predeterminada entre los datos contenidos en entidades y en elementos
Atom.
Quiz tenga un escenario de aplicacin que requiera que los datos de la propiedad devueltos por el servicio
de datos se serialicen de forma personalizada en vez de hacerlo con el formato de fuente estndar. Con
OData , puede personalizar la serializacin de una fuente de distribucin de datos de forma que las

MCT: Luis Dueas

Pag 41 de 128

WCF Data Service


propiedades de una entidad se puedan asignar a elementos de fuente y atributos no usados de una entrada
o a elementos de una entrada en la fuente.

MCT: Luis Dueas

Pag 42 de 128

WCF Data Service

Nota:
La personalizacin de fuentes solo se admite en las fuentes Atom. No se devuelven fuentes personalizadas
cuando se solicita el formato JSON para la fuente devuelta.
Con WCF Data Services , puede definir una asignacin de entidad-propiedad alternativa para una carga
Atom aplicando manualmente los atributos a los tipos de entidad del modelo de datos. El proveedor del
origen de datos del servicio de datos determina cmo debera aplicar estos atributos.
Nota:
Cuando defina las fuentes personalizadas, debe asegurarse de que se incluyan todas las propiedades de
entidad con asignaciones personalizadas en la proyeccin. Cuando no se incluya ninguna propiedad de
entidad asignada en la proyeccin, se puede producir la prdida de datos.

Personalizar fuentes con el proveedor de Entity Framework


El modelo de datos usado con el proveedor de Entity Framework se representa como XML en el archivo
.edmx. En este caso, los atributos que definen las fuentes personalizadas se agregan a los elementos
EntityType y Property, que representan tipos de entidad y propiedades en el modelo de datos. Estos
atributos de personalizacin de fuentes no se definen en el formato de archivo de definicin de esquemas
conceptuales [MC-CSDL], que es el formato que usa el proveedor de Entity Framework para definir el
modelo de datos. Por consiguiente, debe declarar los atributos de personalizacin de fuentes en un espacio
de
nombres
de
esquema
concreto,
que
se
define
como

m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata". El fragmento XML siguiente


muestra los atributos de personalizacin de la fuente aplicados a los elementos Property del tipo de
entidad Products que definen las propiedades ProductName, ReorderLevel y UnitsInStock.
<Property Name="ProductName" Type="String" Nullable="false"
MaxLength="40" Unicode="true" FixedLength="false"
m:FC_TargetPath="SyndicationAuthorName"
m:FC_ContentKind="text"
m:FC_KeepInContent="true"
/>
<Property Name="UnitsInStock" Type="Int16"
m:FC_TargetPath="UnitsInStock"
m:FC_NsPrefix="Northwind"
m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
m:FC_KeepInContent="true"
/>
<Property Name="ReorderLevel" Type="Int16"
m:FC_TargetPath="UnitsInStock/@ReorderLevel"
m:FC_NsPrefix="Northwind"
m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
m:FC_KeepInContent="false"
/>

Estos atributos generan la fuente de distribucin de datos personalizada siguiente para el conjunto de
entidades Products. En la fuente de distribucin de datos personalizada, el valor de propiedad

ProductName se muestra tanto en el elemento author como en el elemento de propiedad ProductName y


la propiedad UnitsInStock se muestra en un elemento personalizado que tiene su propio espacio de
nombres nico y con la propiedad ReorderLevel como atributo:
<entry xml:base="http://localhost:12345/Northwind.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">

MCT: Luis Dueas

Pag 43 de 128

WCF Data Service


<id>http://localhost:12345/Northwind.svc/Products(1)</id>
<title type="text" />
<updated>2009-10-02T05:09:44Z</updated>
<author>
<name>Chai</name>
</author>
<link rel="edit" title="Products" href="Products(1)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Order_Details"
type="application/atom+xml;type=feed" title="Order_Details"
href="Products(1)/Order_Details" />
<category term="NorthwindModel.Products"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ProductID m:type="Edm.Int32">1</d:ProductID>
<d:ProductName>Chai</d:ProductName>
<d:UnitsInStock m:type="Edm.Int16">39</d:UnitsInStock>
<d:SupplierID m:type="Edm.Int32">1</d:SupplierID>
<d:CategoryID m:type="Edm.Int32">1</d:CategoryID>
<d:QuantityPerUnit>10 boxes x 20 bags</d:QuantityPerUnit>
<d:UnitPrice m:type="Edm.Decimal">18.0000</d:UnitPrice>
<d:UnitsOnOrder m:type="Edm.Int16">0</d:UnitsOnOrder>
<d:Discontinued m:type="Edm.Boolean">false</d:Discontinued>
</m:properties>
</content>
<Northwind:UnitsInStock Northwind:ReorderLevel="10"
xmlns:Northwind="http://schemas.examples.microsoft.com/dataservices">39</Northwind:UnitsInStock>
</entry>

Nota:
Dado que Entity Designer no admite las extensiones del modelo de datos, debe modificar manualmente el
archivo XML que contiene el modelo de datos.

Atributos de fuentes personalizadas


En la tabla siguiente se muestran los atributos XML que personalizan fuentes y que puede agregar al
lenguaje de definicin de esquemas conceptuales (CSDL) que define el modelo de datos. Estos atributos son
equivalentes a las propiedades de la clase EntityPropertyMappingAttribute usada con el proveedor de
reflexin.
Nombre de
Descripcin
atributo
Indica el tipo de contenido. Las palabras clave siguientes definen los tipos de contenido
de distribucin:

FC_ContentKind

Palabra clave Descripcin


textEl valor de propiedad se muestra en la fuente como texto.
htmlEl valor de propiedad se muestra en la fuente como HTML.
xhtmlEl valor de propiedad se muestra en la fuente como HTML con formato XML.
Estas palabras clave son equivalentes a los valores de la enumeracin
SyndicationTextContent Kind usada con el proveedor de reflexin.
No se admite este atributo cuando se usan los atributos FC_NsPrefix y FC_NsUri.
Cuando especifique un valor de xhtml para el atributo FC_ContentKind, debe
asegurarse de que el valor de propiedad contenga XML con el formato correcto. El
servicio de datos devuelve el valor sin realizar transformaciones. Adems, debe
asegurarse de que cualquier prefijo de elemento XML del XML devuelto tenga un URI

MCT: Luis Dueas

Pag 44 de 128

WCF Data Service


de espacio de nombres definido en la fuente asignada.
Indica que el valor de propiedad a la que se hace referencia debe incluirse tanto en la
seccin de contenido de la fuente como en la ubicacin asignada. Los valores vlidos
FC_KeepInContent son true y false. Para hacer que la fuente resultante sea compatible con versiones
anteriores de WCF Data Services , especifique el valor true para asegurarse de que el
valor se incluye en la seccin de contenido de la fuente.
FC_NsPrefix

El prefijo del espacio de nombres del elemento XML de una asignacin sin distribucin.
Este atributo debe usarse con el atributo FC_NsUri y no se puede usar con el atributo
FC_ContentKind.

FC_NsUri

El URI del espacio de nombres del elemento XML de una asignacin sin distribucin.
Este atributo debe usarse con el atributo FC_NsPrefix y no se puede usar con el
atributo FC_ContentKind.
La ruta de acceso de la propiedad de la entidad a la que se aplica esta regla de
asignacin de fuentes. Este atributo solo se admite cuando se usa en un elemento
EntityType.
La propiedad SourcePath no puede hacer referencia directamente a un tipo complejo.
Para los tipos complejos, debe usar una expresin de ruta cuyos nombres de propiedad
estn separados por un carcter de barra diagonal (/). Por ejemplo, se permiten los

FC_SourcePath

valores siguientes para un tipo de entidad Person con una propiedad entera Age y una
propiedad compleja Address:

Age
Address/Street
La propiedad SourcePath no puede establecerse en un valor que contenga un espacio
ni en ningn otro carcter que no sea vlido para un nombre de propiedad.
El nombre del elemento de destino de la fuente resultante que debe asignarse a la
propiedad. Este elemento puede ser un elemento definido por la especificacin Atom o
un elemento personalizado.
Las siguientes palabras clave son los valores predefinidos de la ruta de acceso de
destino de distribucin que sealan a una ubicacin concreta de una fuente OData .
Palabra clave Descripcin
SyndicationAuthorEmailEl elemento secundario atom:email del elemento

atom:author.
SyndicationAuthorNameEl elemento secundario atom:name del elemento

atom:author.
SyndicationAuthorUriEl elemento secundario atom:uri del elemento atom:author.
SyndicationContributorEmailEl elemento secundario atom:email del elemento
FC_TargetPath

atom:contributor.
SyndicationContributorNameEl elemento secundario atom:name del elemento

atom:contributor.
SyndicationContributorUriEl elemento secundario atom:uri del elemento

atom:contributor.
SyndicationCustomProperty
Elemento de propiedad personalizada.Cuando se realiza la asignacin a un elemento
personalizado, el destino debe ser una expresin de ruta de acceso cuyos elementos
anidados estn separados mediante una barra diagonal (/) y cuyos atributos se
especifiquen mediante una arroba (@). En el ejemplo siguiente, la cadena
UnitsInStock/@ReorderLevel asigna un valor de propiedad a un atributo denominado
ReorderLevel en un elemento secundario denominado UnitsInStock del elemento de
entrada raz.

MCT: Luis Dueas

Pag 45 de 128

WCF Data Service


<Property Name="ReorderLevel" Type="Int16"
m:FC_TargetPath="UnitsInStock/@ReorderLevel"
m:FC_NsPrefix="Northwind"
m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
m:FC_KeepInContent="false"
/>

Cuando el destino es un nombre de elemento personalizado, tambin se deben


especificar los atributos FC_NsPrefix y FC_NsUri.
SyndicationPublishedEl elemento atom:published.
SyndicationRightsEl elemento atom:rights.
SyndicationSummaryEl elemento atom:summary.
SyndicationTitleEl elemento atom:title.
SyndicationUpdatedEl elemento atom:updated.
Estas palabras clave son equivalentes a los valores de la enumeracin
SyndicationItemProperty usada con el proveedor de reflexin.
Nota:
Los nombres y los valores de los atributos distinguen maysculas de minsculas. Los atributos se pueden
aplicar al elemento EntityType o a uno o varios elementos Property, pero no a ambos.

Personalizar fuentes con el proveedor de reflexin


Para personalizar fuentes para un modelo de datos que se implement usando el proveedor de reflexin,
agregue una o varias instancias del atributo EntityPropertyMappingAttribute a las clases que representan
los tipos de entidad del modelo de datos. Las propiedades de la clase EntityPropertyMappingAttribute
corresponden a los atributos de personalizacin de fuentes que se describen en la seccin anterior. A
continuacin se muestra un ejemplo de la declaracin del tipo Order, con asignacin de la fuente
personalizada definida para ambas propiedades.
Nota:
El modelo de datos para este ejemplo se define en el tema Cmo: Crear un servicio de datos mediante el
proveedor de reflexin (WCF Data Services).
<EntityPropertyMappingAttribute("Customer", _
SyndicationItemProperty.AuthorName, _
SyndicationTextContentKind.Plaintext, True)> _
<EntityPropertyMapping("OrderId", _
SyndicationItemProperty.Title, _
SyndicationTextContentKind.Plaintext, False)> _
<DataServiceKeyAttribute("OrderId")> _
Public Class Order

Estos atributos generan la fuente de distribucin de datos personalizada siguiente para el conjunto de
entidades Orders. En esta fuente personalizada, el valor de propiedad OrderId solo se muestra en el
elemento title de entry y el valor de propiedad Customer se muestra en el elemento author y como
elemento de la propiedad Customer:
<entry xml:base="http://localhost:12345/OrderItems.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:12345/OrderItems.svc/Orders(0)</id>
<title type="text">0</title>
<updated>2009-07-25T21:11:11Z</updated>

MCT: Luis Dueas

Pag 46 de 128

WCF Data Service


<author>
<name>Peter Franken</name>
</author>
<link rel="edit" title="Order" href="Orders(0)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Items"
type="application/atom+xml;type=feed" title="Items" href="Orders(0)/Items" />
<category term="CustomDataService.Order"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Customer>Peter Franken</d:Customer>
</m:properties>
</content>
</entry>

Personalizar fuentes con un proveedor de servicios de datos personalizado


La personalizacin de fuentes para un modelo de datos definido utilizando un proveedor de servicios de
datos
personalizado
se
define
para
un
tipo
de
recurso
llamando
al
mtodo
AddEntityPropertyMappingAttribute en el objeto ResourceType que representa un tipo de entidad en el
modelo de datos.

Usar fuentes personalizadas


Cuando una aplicacin usa directamente una fuente de OData , debe ser capaz de procesar cualquiera de
los elementos y atributos personalizados existentes en la fuente devuelta. Cuando se han implementado
fuentes personalizadas en un modelo de datos, sea cual sea el proveedor del servicio de datos, el extremo
$metadata devuelve la informacin de la fuente personalizada como atributos de fuente personalizados en
el CSDL devuelto por el servicio de datos. Si se usa el cuadro de dilogo Agregar referencia de servicio o
la herramienta datasvcutil.exe para generar las clases del servicio de datos del cliente, se usan los atributos
de fuente personalizados para garantizar que las solicitudes y las respuestas del servicio de datos se
controlen correctamente.

Consideraciones sobre personalizacin de fuentes


Debe considerar lo siguiente cuando defina asignaciones de fuentes personalizadas.
El cliente de WCF Data Services trata los elementos asignados en una fuente como vacos cuando
contengan solo espacio en blanco. Es por ello que los elementos asignados que contengan solo
espacio en blanco no se materializan en el cliente con el mismo espacio en blanco. Para conservar
este espacio en blanco en el cliente, debe establecer el valor de KeepInContext en true en el
atributo de asignacin de fuente.

Requisitos de control de versiones


La personalizacin de fuentes tiene los siguientes requisitos de control de versiones de OData :
La personalizacin de fuente requiere que tanto el cliente como el servicio de datos admitan la
versin 2.0 del protocolo de OData y versiones posteriores.

4.4.1. Cmo: Personalizar fuentes con el proveedor de Entity


Framework
WCF Data Services le permite personalizar la serializacin Atom en una respuesta del servicio de datos para
que las propiedades de una entidad se puedan asignar a los elementos no usados que se definen en el
protocolo AtomPub. En este tema se explica cmo definir los atributos de asignacin para los tipos de
entidad en un modelo de datos definido en un archivo .edmx utilizando el proveedor de Entity Framework.

MCT: Luis Dueas

Pag 47 de 128

WCF Data Service


En este tema modificar manualmente el archivo .edmx generado por la herramienta que contiene el
modelo de datos. Dado que Entity Designer no admite las extensiones al modelo de datos, debe modificar
manualmente el archivo. En el ejemplo de este tema se usan el servicio de datos de ejemplo Northwind y las
clases del servicio de datos del cliente generadas automticamente. Se crean este servicio y las clases de
datos del cliente al completar el tutorial rpido de WCF Data Services.

Para modificar manualmente el archivo Northwind.edmx para agregar los


atributos de personalizacin de fuente
1.
2.
3.

En el Explorador de soluciones, haga clic con el botn secundario del mouse en el archivo
Northwind.edmx y, a continuacin, elija Abrir con.
En el cuadro de dilogo Abrir con - Northwind.edmx, seleccione Editor XML y, a continuacin,
haga clic en Aceptar.
Busque el elemento ConceptualModels y reemplace el tipo de entidad Customers existente con el
siguiente elemento que contiene los atributos de asignacin de personalizacin de la fuente:
<EntityType Name="Customer"
m:FC_SourcePath="CustomerID"
m:FC_TargetPath="SyndicationTitle"
m:FC_ContentKind="text"
m:FC_KeepInContent="true">
<Key>
<PropertyRef Name="CustomerID" />
</Key>
<Property Name="CustomerID" Type="String" Nullable="false" MaxLength="5"
Unicode="true" FixedLength="true" />
<Property Name="ContactName" Type="String" MaxLength="30"
Unicode="true" FixedLength="false"
m:FC_TargetPath="SyndicationAuthorName"
m:FC_ContentKind="text"
m:FC_KeepInContent="true"
/>
<Property Name="CompanyName" Type="String" Nullable="false"
MaxLength="40" Unicode="true" FixedLength="false"
m:FC_TargetPath="CompanyName"
m:FC_NsPrefix="Northwind"
m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
m:FC_KeepInContent="true"
/>
<Property Name="ContactTitle" Type="String" MaxLength="30" Unicode="true" FixedLength="false"
m:FC_TargetPath="SyndicationLinkHref"
m:FC_ContentKind="text"
m:FC_KeepInContent="true"
m:FC_Criteria="SyndicationLinkRel"
m:FC_CriteriaValue="http://NorthwindTraders.com/MyPhotos" />
<Property Name="Address" Type="String" MaxLength="60" Unicode="true" FixedLength="false" />
<Property Name="City" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
<Property Name="Region" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
<Property Name="PostalCode" Type="String" MaxLength="10" Unicode="true" FixedLength="false" />
<Property Name="Country" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
<Property Name="Phone" Type="String" MaxLength="24" Unicode="true" FixedLength="false" />
<Property Name="Fax" Type="String" MaxLength="24" Unicode="true" FixedLength="false" />
<NavigationProperty Name="Orders" Relationship="NorthwindModel.FK_Orders_Customers"
FromRole="Customers" ToRole="Orders" />

MCT: Luis Dueas

Pag 48 de 128

WCF Data Service


</EntityType>

4.
5.

Guarde los cambios y cierre el archivo Northwind.edmx.


(Opcional) Haga clic con el botn secundario en el archivo Northwind.edmx y, a continuacin, haga
clic en Ejecutar herramienta personalizada.
Esto regenera el archivo de capa de objeto, que puede ser necesario.

6.

Compile de nuevo el proyecto.

Ejemplo
En el ejemplo anterior se devuelve el resultado siguiente para el URI

http://myservice/Northwind.svc/Customers('ALFKI').
<entry xml:base="http://localhost:12345/Northwind.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:12345/Northwind.svc/Customers('ALFKI')</id>
<title type="text">ALFKI</title>
<updated>2009-07-27T07:59:43Z</updated>
<author>
<name>Peter Franken</name>
</author>
<link rel="edit" title="Customers" href="Customers('ALFKI')" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Orders"
type="application/atom+xml;type=feed" title="Orders"
href="Customers('ALFKI')/Orders" />
<category term="NorthwindModel.Customers"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ContactName>Peter Franken</d:ContactName>
<d:CompanyName>Alfreds Futterkiste</d:CompanyName>
<d:ContactTitle>Marketing Manager</d:ContactTitle>
<d:Address>Obere Str. 57</d:Address>
<d:City>Berlin</d:City>
<d:Region m:null="true" />
<d:PostalCode>12209</d:PostalCode>
<d:Country>Germany</d:Country>
<d:Phone>089-0877310</d:Phone>
<d:Fax>089-0877554</d:Fax>
</m:properties>
</content>
<Northwind:CompanyName
xmlns:Northwind="http://schemas.examples.microsoft.com/dataservices">Alfreds Futterkiste</Northwind:CompanyName>
</entry>

4.4.2. Cmo: Personalizar fuentes con el proveedor de reflexin


WCF Data Services le permite personalizar la serializacin Atom en una respuesta del servicio de datos para
que las propiedades de una entidad se puedan asignar a los elementos no usados que se definen en el

MCT: Luis Dueas

Pag 49 de 128

WCF Data Service


protocolo AtomPub. En este tema se muestra cmo definir los atributos de asignacin para los tipos de
entidad de un modelo de datos que se define usando el proveedor de reflexin.

Ejemplo
En el ejemplo siguiente, las dos propiedades del tipo Order se asignan a elementos Atom existentes. La
propiedad Product del tipo Item se asigna a un atributo de fuente personalizado en un espacio de nombres
independiente.
Imports System
Imports System.Collections.Generic
Imports System.Data.Services
Imports System.Data.Services.Common
Imports System.Linq
Namespace CustomDataService
<EntityPropertyMappingAttribute("Customer", _
SyndicationItemProperty.AuthorName, _
SyndicationTextContentKind.Plaintext, True)> _
<EntityPropertyMapping("OrderId", _
SyndicationItemProperty.Title, _
SyndicationTextContentKind.Plaintext, False)> _
<DataServiceKeyAttribute("OrderId")> _
Public Class Order
Private _orderId As Integer
Private _customer As String
Private _items As IList(Of Item)
Public Property OrderId() As Integer
Get
Return _orderId
End Get
Set(ByVal value As Integer)
_orderId = value
End Set
End Property
Public Property Customer() As String
Get
Return _customer
End Get
Set(ByVal value As String)
_customer = value
End Set
End Property
Public Property Items() As IList(Of Item)
Get
Return _items
End Get
Set(ByVal value As IList(Of Item))
_items = value
End Set
End Property
End Class
<EntityPropertyMappingAttribute("Product",
SyndicationItemProperty.CategoryTerm, _

MCT: Luis Dueas

Pag 50 de 128

WCF Data Service


true, SyndicationCriteria.CategoryScheme, _
"http://northwindtraders.com/Products")> _
<EntityPropertyMappingAttribute("Url", _
SyndicationItemProperty.LinkHref, false, _
SyndicationCriteria.LinkRel, _
"http://northwindtraders.com/ProductUrl")>
<DataServiceKeyAttribute("Product")> _
Public Class Item
Private _product As String
Private _quantity As Integer
Private _url As String
Public Property Product() As String
Get
Return _product
End Get
Set(ByVal value As String)
_product = value
End Set
End Property
Public Property Quantity() As Integer
Get
Return _quantity
End Get
Set(ByVal value As Integer)
_quantity = value
End Set
End Property
Public Property Url As String
Get
Return _url
End Get
Set(ByVal value As String)
_url = value
End Set
End Property
End Class
Partial Public Class OrderItemData
#Region "Populate Service Data"
Shared _orders As IList(Of Order)
Shared _items As IList(Of Item)
Sub New()
_orders = New Order() { _
New Order() With {.OrderId = 0, .Customer = "Peter Franken", .Items = New List(Of Item)()}, _
New Order() With {.OrderId = 1, .Customer = "Ana Trujillo", .Items = New List(Of Item)()}}
_items = New Item() { _
New Item() With {.Product = "Chai", .Quantity = 10, _
.Url = "http://northwindtraders.com/Teas"}, _
New Item() With {.Product = "Chang", .Quantity = 25, _
.Url = "http://northwindtraders.com/Specialty"}, _
New Item() With {.Product = "Aniseed Syrup", .Quantity = 5, _
.Url = "http://northwindtraders.com/Specialty"}, _
New Item() With {.Product = "Chef Anton's Cajun Seasoning", _

MCT: Luis Dueas

Pag 51 de 128

WCF Data Service


.Quantity = 30, .Url = "http://northwindtraders.com/Spices"}}
_orders(0).Items.Add(_items(0))
_orders(0).Items.Add(_items(1))
_orders(1).Items.Add(_items(2))
_orders(1).Items.Add(_items(3))
End Sub
#End Region
Public ReadOnly Property Orders() As IQueryable(Of Order)
Get
Return _orders.AsQueryable()
End Get
End Property
Public ReadOnly Property Items() As IQueryable(Of Item)
Get
Return _items.AsQueryable()
End Get
End Property
End Class
Public Class OrderItems
Inherits DataService(Of OrderItemData)
' This method is called only once to initialize
' service-wide policies.
Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
config.SetEntitySetAccessRule("Orders", _
EntitySetRights.AllRead _
Or EntitySetRights.AllWrite)
config.SetEntitySetAccessRule("Items", _
EntitySetRights.AllRead _
Or EntitySetRights.AllWrite)
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3
End Sub
End Class
End Namespace

En el ejemplo anterior se devuelve el resultado siguiente para el identificador URI

http://myservice/OrderItems.svc/Orders(0)?$expand=Items .
<entry xml:base="http://localhost:12345/OrderItems.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:12345/OrderItems.svc/Orders(0)</id>
<title type="text">0</title>
<updated>2009-07-25T21:12:30Z</updated>
<author>
<name>Peter Franken</name>
</author>
<link rel="edit" title="Order" href="Orders(0)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Items"
type="application/atom+xml;type=feed" title="Items" href="Orders(0)/Items">
MCT: Luis Dueas

Pag 52 de 128

WCF Data Service


<m:inline>
<feed>
<title type="text">Items</title>
<id>http://localhost:12345/OrderItems.svc/Orders(0)/Items</id>
<updated>2009-07-25T21:12:30Z</updated>
<link rel="self" title="Items" href="Orders(0)/Items" />
<entry>
<id>http://localhost:12345/OrderItems.svc/Items('Chai')</id>
<title type="text" />
<updated>2009-07-25T21:12:30Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Item" href="Items('Chai')" />
<category term="CustomDataService.Item"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Product>Chai</d:Product>
<d:Quantity m:type="Edm.Int32">10</d:Quantity>
</m:properties>
</content>
<orders:productname
xmlns:orders="http://schema.examples.microsoft.com/dataservices">Chai</orders:productname>
</entry>
<entry>
<id>http://localhost:12345/OrderItems.svc/Items('Chang')</id>
<title type="text" />
<updated>2009-07-25T21:12:30Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Item" href="Items('Chang')" />
<category term="CustomDataService.Item"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Product>Chang</d:Product>
<d:Quantity m:type="Edm.Int32">25</d:Quantity>
</m:properties>

MCT: Luis Dueas

Pag 53 de 128

WCF Data Service


</content>
<orders:productname
xmlns:orders="http://schema.examples.microsoft.com/dataservices">Chang</orders:productname>
</entry>
</feed>
</m:inline>
</link>
<category term="CustomDataService.Order"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Customer>Peter Franken</d:Customer>
</m:properties>
</content>
</entry>

4.5. Interceptores
WCF Data Services permite que una aplicacin intercepte los mensajes de solicitud para permitir agregar
una lgica personalizada a una operacin. Puede utilizar esta lgica personalizada para validar los datos de
los mensajes entrantes. Tambin puede utilizarla como restriccin adicional del mbito de una solicitud de
consulta, por ejemplo, para insertar una directiva de autorizacin personalizada por solicitud.
Mtodos con atributos especiales realizan la interceptacin en el servicio de datos. WCF Data Services llama
a estos mtodos en el punto adecuado del procesamiento de mensajes. Los interceptores se definen por
entidad. Los mtodos de interceptor no pueden aceptar los parmetros de la solicitud, como s pueden las
operaciones del servicio. Los mtodos de interceptor de consulta, a los que se llama al procesar una
solicitud GET de HTTP, deben devolver una expresin lambda que determina si los resultados de la consulta
deben devolver una instancia del conjunto de entidades del interceptor. El servicio de datos utiliza esta
expresin para perfeccionar ms la operacin solicitada. El ejemplo siguiente muestra una definicin de un
interceptor de consulta.
' Define a query interceptor for the Orders entity set.
<QueryInterceptor("Orders")> _
Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))

Los interceptores de cambio, a los que se llama al procesar las operaciones que no son de consulta, deben
devolver void (Nothing en Visual Basic). Los mtodos de interceptor de cambio deben aceptar los dos
siguientes parmetros:
1.

Un parmetro de un tipo que es compatible con el tipo de entidad del conjunto de entidades.
Cuando el servicio de datos llama al interceptor de cambio, el valor de este parmetro refleja la
informacin de la entidad que enva la solicitud.

2.

Un parmetro de tipo UpdateOperations. Cuando el servicio de datos llama al interceptor de


cambio, el valor de este parmetro refleja la operacin que la solicitud intenta realizar.

El ejemplo siguiente muestra una definicin de un interceptor de cambio.


' Define a change interceptor for the Products entity set.
<ChangeInterceptor("Products")> _
Public Sub OnChangeProducts(ByVal product As Product, ByVal operations As UpdateOperations)

La interceptacin admite los siguientes atributos.

MCT: Luis Dueas

Pag 54 de 128

WCF Data Service


[QueryInterceptor( EnitySetName )]
Se llama a los mtodos que tienen aplicado el atributo QueryInterceptorAttribute cuando se recibe
una solicitud GET de HTTP para el recurso de conjunto de entidades concreto. Estos mtodos
siempre deben devolver una expresin lambda en el formulario de Expression<Func<T,bool>>.
[ChangeInterceptor( EnitySetName )]
Se llama a los mtodos que tienen aplicado el atributo ChangeInterceptorAttribute cuando se
recibe una solicitud HTTP distinta de GET para el recurso de conjunto de entidades concreto. Estos
mtodos siempre deben devolver void (Nothing en Visual Basic).

4.5.1. Cmo: Interceptar mensajes del servicio de datos


Con WCF Data Services , puede interceptar mensajes de solicitud, lo que le permitir agregar lgica
personalizada a una operacin. Para interceptar un mensaje, se usan mtodos con atributos especiales con
el servicio de datos.

Para definir un interceptor de consultas para el conjunto de entidades Orders


1.

En el proyecto del servicio de datos de Northwind, abra el archivo Northwind.svc.

2.

En la pgina de cdigo de la clase Northwind, agregue la instruccin using siguiente (Imports en


Visual Basic).
Imports System.Linq.Expressions

3.

En la clase Northwind, defina un mtodo de operacin de servicio denominado OnQueryOrders


como sigue:
' Define a query interceptor for the Orders entity set.
<QueryInterceptor("Orders")> _
Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))

Para definir un interceptor de cambios para el conjunto de entidades Products


1.

En el proyecto del servicio de datos de Northwind, abra el archivo Northwind.svc.

2.

En la clase Northwind, defina un mtodo de operacin de servicio denominado

OnChangeProducts como sigue:


' Define a change interceptor for the Products entity set.
<ChangeInterceptor("Products")> _
Public Sub OnChangeProducts(ByVal product As Product, ByVal operations As UpdateOperations)

Ejemplo
En este ejemplo se define un mtodo de interceptor de consultas para el conjunto de entidades Orders que
devuelve una expresin lambda. Esta expresin contiene un delegado que filtra los pedidos ( Orders)
solicitados basndose en los clientes (Customers) relacionados que tienen un nombre de contacto
concreto. El nombre se determina a su vez en funcin del usuario que realiza la solicitud. En este ejemplo se
supone que el servicio de datos se hospeda dentro de una aplicacin web ASP.NET que usa WCF, y que la
autenticacin est habilitada. La clase HttpContext se usa para recuperar el principio de la solicitud actual.
' Define a query interceptor for the Orders entity set.
<QueryInterceptor("Orders")> _
Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))
' Filter the returned orders to only orders
' that belong to a customer that is the current user.
Return Function(o) o.Customer.ContactName = _
HttpContext.Current.User.Identity.Name
End Function

MCT: Luis Dueas

Pag 55 de 128

WCF Data Service


En este ejemplo se define un mtodo interceptor de cambios para el conjunto de entidades Products. Este
mtodo valida la entrada al servicio para una operacin Add o Change y produce una excepcin si se hace
un cambio en un producto que ya no se fabrica. Tambin bloquea la eliminacin de productos como una
operacin no admitida.

' Define a change interceptor for the Products entity set.


<ChangeInterceptor("Products")> _
Public Sub OnChangeProducts(ByVal product As Product, ByVal operations As UpdateOperations)
If operations = UpdateOperations.Change Then
Dim entry As System.Data.Objects.ObjectStateEntry
If Me.CurrentDataSource.ObjectStateManager _
.TryGetObjectStateEntry(product, entry) Then
' Reject changes to a discontinued Product.
' Because the update is already made to the entity by the time the
' change interceptor in invoked, check the original value of the Discontinued
' property in the state entry and reject the change if 'true'.
If CType(entry.OriginalValues("Discontinued"), Boolean) Then
Throw New DataServiceException(400, String.Format(
"A discontinued {0} cannot be modified.", product.ToString()))
Else
Throw New DataServiceException(String.Format( _
"The requested {0} could not be found in the data source.", product.ToString()))
End If
ElseIf (operations = UpdateOperations.Delete) Then
' Block the delete and instead set the Discontinued flag.
Throw New DataServiceException(400, _
"Products cannot be deleted; instead set the Discontinued flag to 'true'")
End If
End If
End

4.6. Desarrollar e implementar WCF Data Services


En este tema se proporciona informacin sobre el desarrollo y la implementacin de WCF Data Services.

Desarrollar el servicio de datos de WCF


Cuando use WCF Data Services para crear un servicio de datos que admita Open Data Protocol (OData) ,
debe realizar las siguientes tareas bsicas durante el desarrollo:
1.

Definir el modelo de datos


WCF Data Services admite distintos proveedores de servicios de datos que le permiten definir un
modelo de datos basado en los datos de diferentes orgenes de datos, desde bases de datos
relacionales hasta tipos de datos enlazados en tiempo de ejecucin.

2.

Crear el servicio de datos


El servicio de datos ms bsico expone una clase que hereda de la clase DataService, con un tipo T
que es el nombre completo del espacio de nombres del contenedor de la entidad.

3.

Configurar el servicio de datos


De forma predeterminada, WCF Data Services deshabilita el acceso a los recursos que expone un
contenedor de entidades. La clase DataServiceConfiguration le permite configurar el acceso a los

MCT: Luis Dueas

Pag 56 de 128

WCF Data Service


recursos y a las operaciones del servicio, especificar la versin admitida de OData , as como definir
otros comportamientos de todo el servicio, como los comportamientos de los procesamientos por
lotes o el nmero mximo de entidades que pueden devolverse en una nica fuente de respuesta.
En este tema se describe principalmente el desarrollo y la implementacin de los servicios de datos
mediante el uso de Visual Studio.

Elegir un servidor web de desarrollo


Cuando desarrolle un servicio de datos de WCF como aplicacin de ASP.NET o un sitio web de ASP.NET
mediante el uso de Visual Studio, dispone de una seleccin de servidores web en los que ejecutar el servicio
de datos durante el desarrollo. Los siguientes servidores web se integran con Visual Studio para facilitar la
prueba y depuracin de los servicios de datos en el equipo local.
1.

Servidor IIS local


Cuando cree un servicio de datos que sea una aplicacin de ASP.NET o un sitio web de ASP.NET
que se ejecute en Internet Information Services (IIS), se recomienda que desarrolle y pruebe el
servicio de datos con IIS en el equipo local. Si se ejecuta el servicio de datos en IIS, se facilita el
seguimiento de las solicitudes HTTP durante el proceso de depuracin. De esta forma, puede
predeterminar los derechos necesarios que requiere IIS para obtener acceso a los archivos, a las
bases de datos y al resto de los recursos que necesita el servicio de datos. Para ejecutar el servicio
de datos en IIS, debe asegurarse de que tanto IIS como Windows Communication Foundation
(WCF) estn instalados y configurados correctamente, as como de conceder acceso a las cuentas
de IIS en las bases de datos y en el sistema de archivos.
Nota:
Debe ejecutar Visual Studio con derechos de administrador para habilitar el entorno de desarrollo
con el fin de configurar el servidor IIS local.

2.

Servidor de desarrollo de Visual Studio


Visual Studio incluye un servidor web integrado, el servidor de desarrollo de Visual Studio, que es el
servidor web predeterminado de los proyectos de ASP.NET. Este servidor web est diseado para
ejecutar proyectos de ASP.NET en el equipo local durante el desarrollo. El Tutorial rpido del
servicio de datos de WCF muestra cmo crear un servicio de datos que se ejecute en el servidor de
desarrollo
de
Visual
Studio.
Debe tener en cuenta las siguientes limitaciones cuando use el servidor de desarrollo de Visual
Studio para desarrollar el servicio de datos:

A este servidor solo se puede acceder desde el equipo local.

Este servidor escucha en localhost y en un puerto especfico, no en el puerto 80, que es el


puerto predeterminado para los mensajes HTTP.

Este servidor ejecuta el servicio de datos en el contexto de su cuenta de usuario actual. Por
ejemplo, si est ejecutando como usuario de nivel de administrador, un servicio de datos
que se ejecute en el servidor de desarrollo de Visual Studio tendr privilegios de nivel de
administrador. De esta forma, el servicio de datos puede acceder a los recursos para los
que no tiene derechos de acceso cuando se implementa en un servidor IIS.

Este servidor no incluye las caractersticas adicionales de IIS, como la autenticacin.

Este servidor no puede administrar los flujos HTTP fragmentados, que enva de forma
predeterminada el cliente de WCF Data Services cuando se accede a los datos binarios
grandes desde el servicio de datos.

MCT: Luis Dueas

Pag 57 de 128

WCF Data Service


o

Este servidor experimenta problemas al procesar el carcter de punto (.) en una direccin
URL, aunque este carcter lo admita WCF Data Services en valores clave.

Sugerencia:
Aunque puede usar el servidor de desarrollo de Visual Studio para probar los servicios de datos
durante el desarrollo, debe probarlos de nuevo despus de implementarlos en un servidor web que
ejecute IIS.
3.

Entorno de desarrollo de Windows Azure


Windows Azure Tools para Visual Studio incluye un conjunto integrado de herramientas para
desarrollar los servicios de Windows Azure en Visual Studio. Con estas herramientas, puede
desarrollar un servicio de datos que se puede implementar en Windows Azure y que puede probar
en el equipo local antes de su implementacin. Use estas herramientas cuando use Visual Studio
para desarrollar un servicio de datos que se ejecute en la plataforma Windows Azure.

Sugerencias de desarrollo
Debe plantearse lo siguiente cuando desarrolle un servicio de datos:
Determine los requisitos de seguridad del servicio de datos, si planea autenticar a los usuarios o
restringir el acceso de usuarios especficos.
Un programa de inspeccin HTTP puede ser muy til cuando se depure un servicio de datos, ya
que permite inspeccionar el contenido de los mensajes de solicitud y respuesta. Cualquier
analizador de paquetes de red que pueda mostrar paquetes sin procesar se puede usar para
inspeccionar las solicitudes HTTP al servicio de datos y las respuestas.
Cuando depure un servicio de datos, quiz desee obtener ms informacin sobre un error desde el
servicio de datos que durante el funcionamiento normal. Puede obtener informacin adicional
sobre el error del servicio de datos si establece la propiedad UseVerboseErrors de la clase
DataServiceConfiguration en true y la propiedad IncludeExceptionDetailInFaults del atributo
ServiceDebugBehavior de la clase de servicio de datos en true. Tambin puede habilitar la traza en
WCF para ver las excepciones producidas en la capa de mensajera HTTP.
Se suele desarrollar un servicio de datos como proyecto de aplicacin de ASP.NET, pero tambin
puede crear el servicio de datos como proyecto de sitio web de ASP.NET en Visual Studio.
Cuando cree un servicio de datos mediante el uso del cuadro de dilogo Agregar nuevo elemento
de Visual Studio, ASP.NET hospeda el servicio de datos en IIS. Mientras que ASP.NET e IIS sean el
host predeterminado para un servicio de datos, se admiten opciones de hospedaje adicionales.

Implementar WCF Data Services


El servicio de datos de WCF proporciona flexibilidad al elegir el proceso que hospede el servicio de datos.
Puede usar Visual Studio para implementar un servicio de datos en las siguientes plataformas:
Servidor web hospedado en IIS
Cuando se desarrolla un servicio de datos como proyecto de ASP.NET, se puede implementar en un
servidor web de IIS mediante los procesos de implementacin estndar de ASP.NET. Visual Studio
proporciona las siguientes tecnologas de implementacin para ASP.NET, en funcin del tipo de
proyecto de ASP.NET que hospede el servicio de datos que est implementando.

Tecnologas de implementacin para aplicaciones web ASP.NET

Paquete de implementacin web

Publicacin con un solo clic

Tecnologas de implementacin para sitios web ASP.NET

MCT: Luis Dueas

Pag 58 de 128

WCF Data Service

Herramienta Copiar sitio web

Herramienta Publicar sitio web

XCopy

Sugerencia:
Antes de intentar implementar el servicio de datos en IIS, asegrese de haber probado la
implementacin en un servidor web que est ejecutando IIS.
Windows Azure
Puede implementar un servicio de datos en Windows Azure con Windows Azure Tools para Visual
Studio. Puede descargar Windows Azure Tools para Visual Studio desde el Centro de descarga de
Microsoft.

Consideraciones de implementacin
Debe plantearse lo siguiente cuando implemente un servicio de datos:
Cuando implemente un servicio de datos que use el proveedor de Entity Framework para acceder a
una base de datos de SQL Server, quiz tambin deba propagar las estructuras de datos, los datos
o ambos con la implementacin del servicio de datos. Visual Studio puede crear automticamente
scripts (archivos .sql) para ello en la base de datos de destino. Estos scripts se pueden incluir en el
paquete de implementacin web de una aplicacin de ASP.NET. En un sitio web de ASP.NET, puede
hacer esto con el Asistente para publicar bases de datos en Visual Studio.
Puesto que WCF Data Services incluye una implementacin bsica de WCF, puede usar Windows
Server AppFabric para supervisar un servicio de datos implementado en IIS que se ejecute en
Windows Server.

4.7. Proteger WCF Data Services


En este tema se describen consideraciones de seguridad especficas del desarrollo. de la implementacin y
la ejecucin de WCF Data Services y de aplicaciones que acceden a servicios compatibles con Open Data
Protocol (OData) . Tambin debe seguir las recomendaciones para crear aplicaciones de .NET Framework
seguras.
Cuando planee cmo proteger un servicio de OData basado en WCF Data Services , debe tratar tanto la
autenticacin, el proceso para detectar y comprobar la identidad de una entidad de seguridad, como la
autorizacin, el proceso para determinar si una entidad de seguridad autenticada puede acceder a los
recursos solicitados. Tambin debe plantearse si va a cifrar el mensaje mediante SSL.

Autenticar las solicitudes de clientes


WCF Data Services no implementa ningn tipo de autenticacin proprio, sino que confa en las medidas de
autenticacin del host de servicio de datos. Es decir, el servicio asume que cualquier solicitud recibida ya la
ha autenticado el host de red y que este ha identificado correctamente la entidad de seguridad para la
solicitud adecuadamente a travs de las interfaces proporcionadas por WCF Data Services . Estas opciones
de autenticacin y los distintos enfoques se describen en el Programa sobre OData y autenticacin.

Opciones de autenticacin para un servicio de datos de WCF


En la siguiente tabla se enumeran algunos de los mecanismos de autenticacin disponibles para ayudar al
usuario a autenticar solicitudes en el servicio de datos de WCF.
Opciones de
Descripcin
autenticacin
Autenticacin
annima

Cuando est habilitada la autenticacin HTTP annima, cualquier entidad de seguridad


puede conectarse al servicio de datos. No se necesitan credenciales para el acceso

MCT: Luis Dueas

Pag 59 de 128

WCF Data Service


annimo. Use esta opcin solo cuando desee permitir a alguien el acceso al servicio de
datos.
Se necesitan credenciales formadas por un nombre de usuario y una contrasea para la
autenticacin. Admite autenticacin de clientes que no sean de Windows.

Autenticacin
bsica e implcita

Nota: de seguridad
Se envan credenciales de autenticacin bsica (nombre de usuario y contrasea) sin
cifrado y se pueden interceptar. La autenticacin implcita enva un hash basado en las
credenciales proporcionadas. De esta forma, la proteccin es mayor que la de la
autenticacin bsica. Ambas son susceptibles de sufrir ataques de tipo " Man in the
middle". Cuando se usan estos mtodos de autenticacin, debe plantearse la
comunicacin cifrada entre el cliente y el servicio de datos mediante el uso de la Capa
de sockets seguros (SSL).
Microsoft Internet Information Services (IIS) proporciona una implementacin de la
autenticacin tanto bsica como implcita para solicitudes HTTP en una aplicacin
ASP.NET. Esta implementacin del proveedor de autenticacin de Windows permite que
una aplicacin cliente de .NET Framework proporcione credenciales en el encabezado
HTTP de la solicitud al servicio de datos para negociar sin ningn problema la
autenticacin de un usuario de Windows.
Cuando desee que el servicio de datos use la autenticacin bsica basada en algn
servicio de autenticacin personalizado y no en las credenciales de Windows, debe
implementar un mdulo HTTP de ASP.NET personalizado para autenticacin.

Autenticacin de
Windows

Autenticacin de
formularios de
ASP.NET

Las credenciales basadas en Windows se intercambian mediante el uso de NTLM o


Kerberos. Este mecanismo es ms seguro que la autenticacin bsica o implcita, pero
requiere que el cliente sea una aplicacin basada en Windows. IIS tambin proporciona
una implementacin de autenticacin de Windows para solicitudes HTTP en una
aplicacin de ASP.NET.
La autenticacin de formularios permite autenticar a los usuarios mediante su propio
cdigo y, a continuacin, conservar un token de autenticacin en una cookie o en la
direccin URL de la pgina. Autentique el nombre de usuario y la contrasea de los
usuarios que usen un formulario de inicio de sesin que cree. Las solicitudes no
autenticadas se redirigen a una pgina de inicio de sesin, en la que el usuario
proporciona las credenciales y enva el formulario. Si la aplicacin autentica la solicitud,
el sistema emite un vale que contiene una clave con el fin de restablecer la identidad
para posteriores solicitudes.
Nota: de seguridad
De forma predeterminada, la cookie que contiene el vale de autenticacin de
formularios no est protegido cuando use la autenticacin de formularios en una
aplicacin web de ASP.NET. Debe plantearse exigir SSL para proteger tanto el vale de
autenticacin como las credenciales de inicio de sesin iniciales.
En la autenticacin basada en notificaciones, el servicio de datos confa en un servicio
de proveedor de identidad de terceros de confianza para autenticar al usuario. El

Autenticacin
basada en
notificaciones

proveedor de identidad autentica positivamente al usuario que solicita acceso a los


recursos del servicio de datos y emite un token que concede acceso a los recursos
solicitados. A continuacin, este token se presenta en el servicio de datos, que concede
acceso al usuario basndose en la relacin de confianza con el servicio de identidad que
emiti el token de acceso.
La ventaja de usar un proveedor de autenticacin basado en notificaciones es que se
pueden usar para autenticar distintos tipos de clientes en dominios de confianza. Si se
usan tales proveedores de terceros, un servicio de datos puede descargar los requisitos
de mantenimiento y autenticacin de usuarios. OAuth 2.0 es un protocolo de

MCT: Luis Dueas

Pag 60 de 128

WCF Data Service


autenticacin basado en notificaciones compatible con el Control de acceso de
AppFabric de Windows Azure para autorizacin federada como servicio. Este protocolo
admite servicios basados en REST.

Autenticacin de la biblioteca cliente


De forma predeterminada, la biblioteca de cliente de WCF Data Services no proporciona credenciales
cuando se realiza una solicitud a un servicio de OData . Cuando el servicio de datos necesita credenciales de
inicio de sesin para autenticar a un usuario, estas credenciales se puedan proporcionar en una clase
NetworkCredential a la que se accede desde la propiedad Credentials de la clase DataServiceContext, como
en el ejemplo siguiente:
' Set the client authentication credentials.
context.Credentials = New NetworkCredential(userName, password, domain)

Cuando el servicio de datos necesite credenciales de inicio de sesin que no se puedan especificar mediante
el uso de un objeto NetworkCredential, como un token basado en notificaciones o una cookie, debe
establecer manualmente los encabezados en la solicitud HTTP, que suelen ser los encabezados
Authorization y Cookie.

Suplantacin
Por lo general, el servicio de datos accede a los recursos necesarios, como los archivos del servidor o de la
base de datos, mediante el uso de las credenciales del proceso de trabajo que hospeda el servicio de datos.
Al usar la suplantacin, las aplicaciones ASP.NET se pueden ejecutar con la identidad de Windows (cuenta
de usuario) del usuario que realiza la solicitud. La suplantacin se suele usar en aplicaciones que confan en
IIS para autenticar al usuario y las credenciales de esta entidad de seguridad se usan para obtener acceso a
los recursos necesarios.

Configurar la autorizacin del servicio de datos


La autorizacin es la concesin de acceso a los recursos de la aplicacin a una entidad de seguridad o a un
proceso que se identifique basndose en una autenticacin correcta previa. Como regla general, solo debe
conceder los derechos estrictamente necesarios a los usuarios del servicio de datos para realizar las
operaciones que necesiten las aplicaciones cliente.

Restringir el acceso a los recursos del servicio de datos


De forma predeterminada, WCF Data Services permite conceder acceso comn de lectura y escritura a los
recursos del servicio de datos (conjunto de entidades y operaciones de servicio) a cualquier usuario que
pueda acceder al servicio de datos. Las reglas que definen el acceso de lectura y escritura se pueden definir
por separado para cada conjunto de entidades expuesto por el servicio de datos, as como a las operaciones
de servicio. Se recomienda limitar el acceso tanto de lectura como de escritura a solo los recursos que
necesite la aplicacin cliente.

Implementar interceptores basados en roles


Los interceptores permiten interceptar solicitudes en los recursos del servicio de datos antes de que acte
en ellos dicho servicio. Los interceptores permiten tomar decisiones de autorizacin basadas en el usuario
autenticado que realiza la solicitud.

Restringir el acceso al almacn de datos persistentes y a los recursos locales


A las cuentas que se usan para acceder al almacn persistente se les deben conceder solo los derechos
estrictamente necesarios en una base de datos o en el sistema de archivos para admitir los requisitos del
servicio de datos. Cuando se usa la autenticacin annima, se trata de la cuenta usada para ejecutar la
aplicacin de hospedaje. Cuando se usa la suplantacin, a los usuarios autenticados se les debe conceder
acceso a estos recursos, normalmente como parte de un grupo de Windows.

Otras consideraciones de seguridad


Proteger los datos de la carga
OData se basa en el protocolo HTTP. En un mensaje HTTP, el encabezado puede contener valiosas
credenciales de usuario, en funcin de la autenticacin implementada por el servicio de datos. El cuerpo del

MCT: Luis Dueas

Pag 61 de 128

WCF Data Service


mensaje tambin puede contener datos valiosos de clientes que se deben proteger. En ambos casos, se
recomienda que use SSL para proteger esta informacin a travs de la conexin.

Cookies y encabezados del mensaje ignorados


Los encabezados de solicitudes HTTP, que no sean los que declaran los tipos de contenido y las ubicaciones
de los recursos, se ignoran y nunca los establece el servicio de datos.
Las cookies se pueden usar como parte de un esquema de autenticacin, por ejemplo, con la autenticacin
de los formularios de ASP.NET. WCF Data Services ignora, sin embargo, las cookies HTTP establecidas en
una solicitud entrante. El host de un servicio de datos puede procesar la cookie, pero el tiempo de ejecucin
de WCF Data Services nunca analiza ni devuelve cookies. La biblioteca cliente de WCF Data Services
tampoco procesa las cookies enviadas en la respuesta.

Requisitos personalizados de hospedaje


De forma predeterminada, WCF Data Services se crea como aplicacin de ASP.NET hospedada en IIS. De
esta forma, el servicio de datos puede sacar provecho de los comportamientos seguros de esta plataforma.
Puede definir los WCF Data Services hospedados por un host personalizado. Los componentes y la
plataforma que hospedan un servicio de datos deben asegurar los siguientes comportamientos de
seguridad para impedir ataques contra el servicio de datos:
Limitar la longitud del URI aceptada en una solicitud del servicio de datos para todas las
operaciones posibles.
Limitar el tamao de los mensajes HTTP tanto entrantes como salientes.
Limitar el nmero total de solicitudes pendientes en cualquier momento dado.
Limitar la longitud de los encabezados HTTP y sus valores, as como proporcionar acceso a WCF
Data Services a los datos del encabezado.
Detectar y contraatacar los ataques conocidos, como ataques SYN de TCP y de reproduccin de
mensajes.

Los valores ya no se codifican


Los valores de propiedad enviados al servicio de datos ya no los codifica el tiempo de ejecucin de WCF
Data Services . Por ejemplo, cuando una propiedad de cadena de una entidad contiene contenido HTML
con formato, el servicio de datos no codifica las etiquetas en HTML. Adems, el servicio de datos ya no
codifica los valores de propiedad de la respuesta. Asimismo, la biblioteca cliente ya no efecta ningn tipo
de codificacin adicional.

Consideraciones sobre aplicaciones cliente


Las consideraciones de seguridad siguientes se aplican a las aplicaciones que usan el cliente de WCF Data
Services para acceder a los servicios de OData :
La biblioteca cliente asume que los protocolos usados para acceder al servicio de datos
proporcionan un nivel de seguridad adecuado.
La biblioteca cliente usa todos los valores predeterminados para las opciones de tiempos de espera
y de anlisis de las pilas de transporte proporcionadas por la plataforma subyacente.
La biblioteca cliente no lee la configuracin a partir de los archivos de configuracin de la
aplicacin.
La biblioteca cliente no implementa los mecanismos de acceso entre dominios. En su lugar, confa
en los mecanismos proporcionados por la pila HTTP subyacente.
La biblioteca cliente no dispone de elementos de interfaz de usuario y nunca intenta mostrar o
presentar los datos que recibe o enva.
Se recomienda que las aplicaciones cliente siempre validen la entrada del usuario, as como los
datos aceptados de servicios que no sean de confianza.

4.8. Hospedar el servicio de datos


MCT: Luis Dueas

Pag 62 de 128

WCF Data Service


Mediante WCF Data Services , puede crear un servicio que exponga datos como una fuente de Open Data
Protocol (OData) . Este servicio de datos se define como una clase que hereda de DataService. Esta clase
proporciona la funcionalidad necesaria para procesar mensajes de solicitud, realizar actualizaciones en el
origen de datos y generar mensajes de respuesta, como requiere OData . Sin embargo, un servicio de datos
no puede enlazar solicitudes HTTP de entrada ni escucharlas en un socket de red. Para esta funcionalidad
necesaria, el servicio de datos se basa en un componente de hospedaje.
El host del servicio de datos realiza las siguientes tareas en nombre del servicio de datos:
Realiza escuchas de las solicitudes y las enruta al servicio de datos.
Crea una instancia del servicio de datos para cada solicitud.
Solicita al servicio de datos que procese la solicitud entrante.
Enva la respuesta en nombre del servicio de datos.
Para simplificar el hospedaje de un servicio de datos, WCF Data Services est diseado para integrarse con
Windows Communication Foundation (WCF). El servicio de datos proporciona una implementacin WCF
predeterminada que acta como host del servicio de datos en una aplicacin ASP.NET. Por consiguiente, un
servicio de datos se puede hospedar de una de las siguientes maneras:
En una aplicacin ASP.NET.
En una aplicacin administrada que admita servicios WCF autohospedados.
En algn otro host del servicio de datos personalizado.

Hospedar un servicio de datos en una aplicacin ASP.NET


Cuando se usa el cuadro de dilogo Agregar nuevo elemento en Visual Studio para definir un servicio de
datos en una aplicacin ASP.NET, la herramienta genera dos nuevos archivos en el proyecto. El primer
archivo tiene una extensin .svc e indica al tiempo de ejecucin de WCF cmo crear instancias del servicio
de datos. A continuacin, se muestra un ejemplo de este archivo para el servicio de datos de ejemplo
Northwind que se cre al completar el tutorial rpido:
<%@ ServiceHost Language="C#"
Factory="System.Data.Services.DataServiceHostFactory,
System.Data.Services, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"
Service="NorthwindService.Northwind" %>

Esta directiva indica a la aplicacin que debe crear el host del servicio para la clase del servicio de datos con
nombre utilizando la clase DataServiceHostFactory.
La pgina de cdigo subyacente del archivo .svc contiene la clase que es la implementacin del propio
servicio de datos, el cual se define para el servicio de datos de ejemplo Northwind del siguiente modo:
Public Class Northwind
Inherits DataService(Of NorthwindEntities)

Dado que un servicio de datos se comporta como un servicio WCF, el servicio de datos se integra con
ASP.NET y sigue el modelo de programacin web de WCF.

Servicios WCF autohospedados


Dado que incorpora una implementacin WCF, WCF Data Services admite el servicio de datos
autohospedado como un servicio WCF. Un servicio puede hospedarse a s mismo en cualquier aplicacin
.NET Framework, como una aplicacin de consola. La clase DataServiceHost, que hereda de
WebServiceHost, se utiliza para crear instancias del servicio de datos en una direccin concreta.
El autohospedaje se puede utilizar para el desarrollo y las pruebas porque facilita el despliegue y la solucin
de problemas del servicio. Sin embargo, este tipo de hospedaje no ofrece las caractersticas de
administracin y hospedaje avanzadas que proporciona ASP.NET o Internet Information Services (IIS).

Definir un host de servicio de datos personalizado

MCT: Luis Dueas

Pag 63 de 128

WCF Data Service


Para los casos en los que la implementacin de un host de WCF sea demasiado restrictiva, se puede definir
tambin un host personalizado para un servicio de datos. Cualquier clase que implemente la interfaz
IDataServiceHost se puede utilizar como el host de red de un servicio de datos. Un host personalizado debe
implementar la interfaz IDataServiceHost y ser capaz de controlar las siguientes responsabilidades bsicas
del host del servicio de datos:
Proporcionar la ruta de acceso raz del servicio al servicio de datos.
Procesar la informacin de encabezados de respuesta y solicitud en la implementacin de miembro
de IDataServiceHost adecuada.
Controlar las excepciones iniciadas por el servicio de datos.
Validar parmetros en la cadena de consulta.

4.9. Trabajar con varias versiones de WCF Data Services


Open Data Protocol (OData) le permite tener acceso a un origen de datos de forma remota mediante
protocolos de Internet estndar sobre HTTP. A medida que se lanzan nuevas versiones de OData , quiz las
aplicaciones cliente no usen la misma versin de OData que admite el servicio de datos. Puede que una
aplicacin cliente antigua tenga acceso a un servicio de datos utilizando una versin ms reciente de OData
o quiz una aplicacin cliente use una versin ms reciente de la biblioteca de cliente de WCF Data Services
que admite una versin ms reciente de OData que la de la fuente de OData a la que se est obteniendo
acceso.
WCF Data Services aumenta la compatibilidad que proporciona OData para administrar tales escenarios de
versin. Tambin existe soporte tcnico para generar y usar metadatos del modelo de datos con el fin de
crear las clases de servicio de datos de cliente cuando el cliente usa una versin distinta de OData de la que
usa el servicio de datos.

Versiones del protocolo


El servicio de datos se puede configurar para definir la versin ms alta del protocolo OData que usar el
servicio, independientemente de la versin solicitada por el cliente. Para ello, especifique un valor de la
enumeracin DataServiceProtocolVersion para la propiedad MaxProtocolVersion de la clase
DataServiceBehavior que usa el servicio de datos.
Cuando una aplicacin usa las bibliotecas de cliente de WCF Data Services para tener acceso a un servicio
de datos, las bibliotecas establecen automticamente estos encabezados en los valores correctos, en
funcin de la versin de OData y de las caractersticas que se usan en la aplicacin. De forma
predeterminada, WCF Data Services utiliza la versin de protocolo ms baja que admita la operacin
solicitada.
En la siguiente tabla se detallan las versiones de .NET Framework y Silverlight que incluyen compatibilidad
con WCF Data Services para versiones especficas del protocolo OData .
Versin del protocolo OData
Compatibilidad introducida en
Versin 1

.NET Framework versin 3.5 Service Pack 1 (SP1)


Versin 3 de Silverlight.
.NET Framework versin 4

Versin 2

Actualizacin a .NET Framework versin 3.5 SP1.


Versin 4 de Silverlight.

Versiones de metadatos
De forma predeterminada, WCF Data Services usa la versin 1.1 de CSDL para representar un modelo de
datos. Este siempre es el caso para los modelos de datos basados en un proveedor de reflexin o en un
proveedor del servicio de datos personalizados. No obstante, cuando se define un modelo de datos

MCT: Luis Dueas

Pag 64 de 128

WCF Data Service


mediante Entity Framework , la versin devuelta de CSDL es la misma que la que usa Entity Framework . La
versin de CSDL la determina el espacio de nombres del elemento Schema.
El elemento DataServices de los metadatos devueltos tambin contiene un atributo DataServiceVersion,
que tiene el mismo valor que el encabezado DataServiceVersion del mensaje de respuesta. Las
aplicaciones cliente, como el cuadro de dilogo Agregar referencia de servicio de Visual Studio, usan esta
informacin para generar las clases del servicio de datos de cliente que funcionen correctamente con la
versin de WCF Data Services que hospede el servicio de datos.

5. Biblioteca de cliente de WCF Data Services


Cualquier aplicacin puede interactuar con un servicio de datos basado en Open Data Protocol (OData) si
puede enviar una solicitud HTTP y procesar la fuente de OData que devuelve un servicio de datos. Esta
interoperabilidad permite tener acceso a los servicios basados en OData de una amplia gama de
aplicaciones basadas en web. WCF Data Services incluye bibliotecas de cliente que proporcionan una
experiencia de programacin ms enriquecida cuando se usan fuentes OData desde aplicaciones basadas
en .NET Framework o Silverlight.
Las dos clases principales de la biblioteca cliente son la clase DataServiceContext y la clase
DataServiceQuery. La clase DataServiceContext encapsula las operaciones admitidas en un servicio de
datos determinado. Los servicios de OData carecen de estado, pero no ocurre lo mismo con el contexto. Por
consiguiente, puede usar la clase DataServiceContext para mantener el estado en el cliente entre las
interacciones con el servicio de datos para admitir caractersticas como la administracin de cambios. Esta
clase tambin administra las identidades y realiza el seguimiento de los cambios. La clase
DataServiceQuery representa una consulta en un conjunto de entidades concreto.
En esta seccin se describe cmo usar las bibliotecas de cliente para obtener acceso a los datos de una
aplicacin cliente de .NET Framework y para cambiarlos. Existen otras bibliotecas de cliente disponibles que
permiten usar una fuente de OData en otros tipos de aplicaciones.

5.1. Generar la biblioteca de cliente del servicio de datos


Un servicio de datos que implementa Open Data Protocol (OData) puede devolver un documento de
metadatos del servicio que describe el modelo de datos expuesto por la fuente de OData . Puede usar el
cuadro de dilogo Agregar referencia de servicio de Visual Studio para agregar una referencia a un
servicio basado en OData . Cuando se usa esta herramienta para agregar una referencia a los metadatos
que se devuelven en una fuente de OData en un proyecto de cliente, realiza las acciones siguientes:
Solicita el documento de metadatos del servicio al servicio de datos e interpreta los metadatos
devueltos.
Nota:
Los metadatos devueltos se almacenan en el proyecto de cliente como un archivo .edmx. Este
archivo .edmx no se puede abrir utilizando el diseador de Entity Data Model ya que no tiene el
mismo formato que un archivo .edmx utilizado por Entity Framework. Puede ver este archivo de
metadatos utilizando el editor XML o cualquier editor de texto.
Genera una representacin del servicio como una clase de contenedor de entidades que hereda de
DataServiceContext. Esta clase de contenedor de entidades generada es similar al contenedor de
entidades generado por las herramientas de Entity Data Model.
Genera clases de datos para los tipos de modelo de entidad que detecta en los metadatos del
servicio.
Agrega al proyecto una referencia al ensamblado System.Data.Services.Client.
Las clases del servicio de datos del cliente tambin se pueden generar usando la herramienta
DataSvcUtil.exe en el smbolo del sistema.

MCT: Luis Dueas

Pag 65 de 128

WCF Data Service

Asignacin de tipos de datos del cliente


Cuando se usa el cuadro de dilogo Agregar referencia de servicio en Visual Studio o la herramienta
DataSvcUtil.exe para generar clases de datos del cliente que se basan en una fuente de OData , los tipos
de datos de .NET Framework se asignan a los tipos primitivos del modelo de datos de la siguiente forma:
Tipo del modelo de datos Tipo de datos de .NET Framework
Edm.Binary

Byte []

Edm.Boolean

Boolean

Edm.Byte

Byte

Edm.DateTime

DateTime

Edm.Decimal

Decimal

Edm.Double

Double

Edm.Guid

Guid

Edm.Int16

Int16

Edm.Int32

Int32

Edm.Int64

Int64

Edm.SByte

SByte

Edm.Single

Single

Edm.String

String

5.1.1. Utilidad de cliente de WCF Data Service (DataSvcUtil.exe)


DataSvcUtil.exe es una herramienta de lnea de comandos proporcionada por WCF Data Services que utiliza
una fuente de Open Data Protocol (OData) y genera las clases de servicio de datos de cliente necesarias
para tener acceso a un servicio de datos desde una aplicacin cliente de .NET Framework. Esta utilidad
puede generar las clases de datos utilizando los siguientes orgenes de metadatos:
El URI de la raz de un servicio de datos. La utilidad solicita el documento de metadatos de servicio,
que describe el modelo de datos expuesto por el servicio de datos.
Un archivo de modelo de datos (.csdl) definido mediante el lenguaje de definicin de esquemas
conceptuales (CSDL), tal y como se define en [MC-CSDL]: Formato de archivos de definicin de
esquemas conceptuales.
Un archivo .edmx creado mediante las herramientas de Entity Data Model que se proporcionan con
Entity Framework.
La herramienta DataSvcUtil.exe se instala en el directorio de .NET Framework. En muchos casos, se
encuentra en C:\Windows\Microsoft.NET\Framework\v4.0. Para los sistemas de 64 bits, se encuentra en
C:\Windows\Microsoft.NET\Framework64\v4.0. Tambin puede tener acceso a la herramienta
DataSvcUtil.exe desde el smbolo del sistema de Visual Studio (haga clic en Inicio, seleccione Todos los
programas, Microsoft Visual Studio 2010, Visual Studio Tools y haga clic en Smbolo del sistema de
Visual Studio 2010).

datasvcutil /out:file [/in:file | /uri:serviceuri] [/dataservicecollection] [/language:devlang] [/nologo]


[/version:ver] [/help]
Parmetros
Opcin
/dataservicecollection
/help

MCT: Luis Dueas

Descripcin
Especifica que tambin se genera el cdigo necesario para enlazar los objetos a los
controles.
Muestra la sintaxis de comandos y opciones para la herramienta.

Pag 66 de 128

WCF Data Service


O bien
/?
/in: <archivo>

Especifica el archivo .csdl o .edmx o un directorio donde se encuentra el archivo.

/language:[VB|CSharp]

Especifica el lenguaje de los archivos de cdigo fuente generados. El lenguaje


predeterminado es C#.

/nologo

Evita que se muestre el mensaje de copyright.

/out: <archivo>

Especifica el nombre del archivo de cdigo fuente que contiene las clases de
servicio de datos de cliente generadas.

/uri: <string>

El URI de la fuente de OData .

/version:[1.0|2.0]

Especifica la versin superior aceptada de OData . La versin se determina


basndose en el atributo DataServiceVersion del elemento DataService en los
metadatos devueltos del servicio de datos. Al especificar el parmetro
/dataservicecollection, tambin debe especificar /version:2.0 para habilitar el
enlace de datos.

5.1.2. Cmo: Agregar una referencia a un servicio de datos


Puede usar el cuadro de dilogo Agregar referencia de servicio de Visual Studio para agregar una
referencia a WCF Data Services . Esto le permite tener acceso ms fcilmente a un servicio de datos en una
aplicacin cliente desarrollada en Visual Studio. Cuando complete este procedimiento, se generarn clases
de datos basadas en los metadatos que se obtienen del servicio de datos.

Para agregar una referencia a un servicio de datos


1.
2.
3.

(Opcional) Si el servicio de datos no forma parte de la solucin y no se est ejecutando, incielo y


anote el URI del mismo.
Haga clic con el botn secundario en el proyecto de cliente y, a continuacin, seleccione Agregar
referencia de servicio.
Si el servicio de datos forma parte de la solucin actual, haga clic en Detectar.
O bien
En el cuadro de texto Direccin, escriba la direccin URL base del servicio de datos, como por
ejemplo, http://localhost:1234/Northwind.svc y, a continuacin, haga clic en Ir.

4.

Haga clic en Aceptar.


De este modo se agrega un nuevo archivo de cdigo que contiene las clases de datos que se usan
para obtener acceso e interactuar con los recursos del servicio de datos como objetos.

5.1.3. Cmo: Generar manualmente clases del servicio de datos del


cliente
WCF Data Services se integra con Visual Studio para permitir la generacin automtica de las clases del
servicio de datos del cliente cuando se usa el cuadro de dilogo Agregar referencia de servicio para
agregar una referencia a un servicio de datos en un proyecto de Visual Studio. Tambin puede generar
manualmente las mismas clases del servicio de datos del cliente mediante la herramienta de generacin de
cdigo DataSvcUtil.exe. Esta herramienta, que se incluye con WCF Data Services , genera las clases de .NET
Framework a partir de la definicin del servicio de datos. Tambin se puede usar para generar clases del
servicio de datos a partir del archivo de modelo conceptual (.csdl) y del archivo .edmx que representa un
modelo de Entity Framework en un proyecto Visual Studio.
El ejemplo usado en este tema crea clases del servicio de datos del cliente basadas en el servicio de datos
de ejemplo de Northwind. Este servicio se crea cuando se completa el Tutorial rpido de WCF Data Services.
Algunos ejemplos de este tema requieren el archivo de modelo conceptual para el modelo de Northwind.
Algunos ejemplos de este tema requieren el archivo de modelo conceptual .edmx para el modelo de
Northwind.

MCT: Luis Dueas

Pag 67 de 128

WCF Data Service

Para generar clases de C# que admitan el enlace de datos


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\DataSvcUtil.exe" /dataservicecollection /version:2.0 /language:CSharp
/out:Northwind.cs /uri:http://localhost:12345/Northwind.svc

Nota:
Debe reemplazar el valor proporcionado para el parmetro /uri: con el URI de la instancia del
servicio de datos de ejemplo de Northwind.

Para generar clases Visual Basic que admitan el enlace de datos


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\DataSvcUtil.exe" /dataservicecollection /version:2.0 /language:VB
/out:Northwind.vb /uri:http://localhost:12345/Northwind.svc

Para generar clases de C# basadas en el URI de servicio


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\DataSvcUtil.exe" /language:CSharp /out:northwind.cs
/uri:http://localhost:12345/Northwind.svc

Para generar clases de Visual Basic basadas en el URI de servicio


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\datasvcutil.exe" /language:VB /out:Northwind.vb
/uri:http://localhost:12345/Northwind.svc

Para generar clases de C# basadas en el archivo de modelo conceptual (CSDL)


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\datasvcutil.exe" /language:CSharp /in:Northwind.csdl /out:Northwind.cs

Para generar clases de Visual Basic basadas en el archivo de modelo conceptual


(CSDL)
En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\datasvcutil.exe" /language:VB /in:Northwind.csdl /out:Northwind.vb

Para generar clases de C# basadas en el archivo .edmx


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\datasvcutil.exe" /language:CSharp /in:Northwind.edmx /out:c:\northwind.cs

Para generar clases de Visual Basic basadas en el archivo .edmx


En el smbolo del sistema, ejecute el siguiente comando sin los saltos de lnea:
"%windir%\Microsoft.NET\Framework\v3.5\datasvcutil.exe" /language:VB /in:Northwind.edmx /out:c:\northwind.vb

5.2. Consultar el servicio de datos


La biblioteca de cliente de WCF Data Services le permite ejecutar consultas en un servicio de datos
mediante los conocidos modelos de programacin de .NET Framework, incluido el uso de Language
Integrated Query (LINQ). La biblioteca de cliente traduce una consulta, que se define en el cliente como
instancia de la clase DataServiceQuery, en un mensaje de solicitud HTTP GET. La biblioteca recibe el mensaje
de respuesta y lo traduce en instancias de las clases del servicio de datos de cliente. El seguimiento de estas
clases lo realiza la clase DataServiceContext a la que pertenece la clase DataServiceQuery.

Consultas del servicio de datos

MCT: Luis Dueas

Pag 68 de 128

WCF Data Service


La clase DataServiceQuery genrica representa una consulta que devuelve una coleccin de cero o ms
instancias de tipo de entidad. Una consulta del servicio de datos siempre pertenece al contexto de un
servicio de datos existente. Este contexto mantiene la informacin necesaria del URI del servicio y la de los
metadatos para crear y ejecutar la consulta.
Cuando se usa el cuadro de dilogo Agregar referencia de servicio para agregar un servicio de datos a
una aplicacin cliente basada en .NET Framework, se crea una clase de contendor de entidades que hereda
de la clase DataServiceContext. Esta clase incluye propiedades que devuelven instancias de
DataServiceQuery con tipo. Existe una propiedad para cada conjunto de entidades que expone el servicio
de datos. Estas propiedades facilitan la creacin de una instancia de DataServiceQuery con tipo.
Las consultas se ejecutan en los escenarios siguientes:
Cuando se enumeran los resultados implcitamente, por ejemplo:

Cuando se enumera una propiedad de la clase DataServiceContext que representa un


conjunto de entidades, como ocurre en un bucle foreach (C#) o For Each (Visual Basic).

Cuando se asigna la consulta a una coleccin List.

Cuando se llama explcitamente a los mtodos Execute o BeginExecute.


Cuando se llama a un operador de ejecucin de consultas LINQ, como First o Single.
Cuando se ejecuta la siguiente consulta, devuelve todas las entidades Customers del servicio de datos de
Northwind:
' Define a new query for Customers.
Dim query As DataServiceQuery(Of Customer) = context.Customers

El cliente de WCF Data Services admite consultas para objetos enlazados en tiempo de ejecucin, como
cuando usa el tipo dynamic en C#. Sin embargo, por razones de rendimiento siempre debe redactar
consultas fuertemente tipadas en el servicio de datos. El cliente no admite los objetos de tipo y dinmicos
de la clase Tuple.

Consultas LINQ
Puesto que la clase DataServiceQuery implementa la interfaz IQueryable definida por LINQ, la biblioteca de
cliente de WCF Data Services puede transformar consultas LINQ en datos del conjunto de entidades en un
URI que representa una expresin de consulta evaluada en un recurso del servicio de datos. En el siguiente
ejemplo hay una consulta LINQ que es equivalente a la clase DataServiceQuery anterior que devuelve

Orders con un costo de flete de ms de 30 dlares y ordena los resultados por el costo del flete:
Dim selectedOrders = From o In context.Orders _
Where (o.Freight > 30) _
Order By o.ShippedDate Descending _
Select o

Esta consulta LINQ se traduce en el siguiente URI de la consulta que se ejecuta en el servicio de base de
datos del tutorial rpido basado en Northwind:

http://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30
Nota:
El conjunto de consultas que se pueden expresar en la sintaxis de LINQ es ms amplio que los habilitados
en la sintaxis URI basada en REST (Representational State Transfer) usada por los servicios de datos. Cuando
la consulta no se puede asignar a ningn URI del servicio de datos de destino, se produce una excepcin
NotSupportedException.

Agregar opciones de consulta


Las consultas del servicio de datos admiten todas las opciones de consulta que proporciona WCF Data
Services . Llame al mtodo AddQueryOption para anexar las opciones de consulta a una instancia de la clase
DataServiceQuery. El mtodo AddQueryOption devuelve una nueva instancia de la clase
DataServiceQuery que es equivalente a la consulta original pero con un conjunto de opciones de consulta

MCT: Luis Dueas

Pag 69 de 128

WCF Data Service


nuevo. Cuando se ejecuta la siguiente consulta, devuelve el valor Orders filtrado por el valor Freight y
ordenado por OrderID, en orden descendente:
' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = context.Orders _
.AddQueryOption("$filter", "Freight gt 30") _
.AddQueryOption("$orderby", "OrderID desc")

Puede usar la opcin de consulta $orderby tanto para ordenar como para filtrar una consulta basada en
una sola propiedad, como en el siguiente ejemplo que filtra y ordena los objetos Orders devueltos basados
en el valor de la propiedad Freight:
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' that also orders the result by the Freight value, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = _
context.Orders.AddQueryOption("$orderby", "Freight gt 30 desc")
Try
' Enumerate over the results of the query.
For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Freight: {1}", _
order.OrderID, order.Freight)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException( _
"An error occurred during query execution.", ex)
End Try

Puede llamar al mtodo AddQueryOption consecutivamente para construir expresiones de consulta


complejas.
Las opciones de consulta le proporcionan otra forma de expresar los componentes estticos de una
consulta LINQ.
Nota:
La opcin de consulta $select no se puede agregar a ningn URI de la consulta mediante el uso del mtodo
AddQueryOption. Se recomienda usar el mtodo Select de LINQ para que el cliente genere la opcin de
consulta $select en el URI de solicitud.

Ejecucin de cliente frente a servidor


El cliente ejecuta una consulta en dos partes. Siempre que sea posible, las expresiones de una consulta
primero se evalan en el cliente y, a continuacin, se generan y se envan al servicio de datos para su
evaluacin en los datos del servicio. Considere la siguiente consulta LINQ:
Dim basePrice As Integer = 100
Dim discount As Decimal = Convert.ToDecimal(0.1)
' Define a query that returns products based on a
' calculation that is determined on the client.
Dim productsQuery = From p In context.Products
Where p.UnitPrice >
(basePrice - (basePrice * discount)) AndAlso
p.ProductName.Contains("bike")
Select p

MCT: Luis Dueas

Pag 70 de 128

WCF Data Service


En este ejemplo, la expresin (basePrice (basePrice * discount)) se evala en el cliente. Por ello, el URI
de la consulta real http://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and

substringof('bike',ProductName) que se enva al servicio de datos contiene el valor decimal ya calculado de


90 en la clusula de filtro. El resto de las partes de la expresin de filtrado, incluida la expresin de
subcadena, las evala el servicio de datos. Las expresiones que se evalan en el cliente siguen la semntica
de Common Language Runtime (CLR), mientras que las expresiones enviadas al servicio de datos confan en
la implementacin del servicio de datos del protocolo OData . Debe tener en cuenta los escenarios en los
que esta evaluacin independiente pueda causar resultados inesperados, como cuando tanto el cliente
como el servidor realicen evaluaciones basadas en la hora en distintas zonas horarias.

Respuestas de consulta
Cuando se ejecuta, el objeto DataServiceQuery devuelve una interfaz IEnumerable del tipo de entidad
solicitado. Este resultado de consulta se puede convertir en un objeto QueryOperationResponse, como en el
siguiente ejemplo:
' Execute the query for all customers and get the response object.
Dim response As QueryOperationResponse(Of Customer) = _
CType(query.Execute(), QueryOperationResponse(Of Customer))

Las instancias de tipo de entidad que representan entidades del servicio de datos se crean en el cliente
mediante un proceso denominado materializacin de objetos. El objeto QueryOperationResponse
implementa IEnumerable para proporcionar acceso a los resultados de la consulta.
QueryOperationResponse tambin tiene los siguientes miembros que le permiten tener acceso a
informacin adicional sobre el resultado de una consulta:
La propiedad Error: obtiene un error provocado por la operacin, si se ha producido alguna.
La propiedad Headers: contiene una coleccin de encabezados de respuesta HTTP asociados con la
respuesta de la consulta.
La propiedad Query: obtiene
QueryOperationResponse.

el

objeto

DataServiceQuery

original

generado

por

La propiedad StatusCode: obtiene el cdigo de respuesta HTTP para la respuesta de la consulta.


La propiedad TotalCount: obtiene el nmero total de entidades establecidas cuando se llam al
mtodo IncludeTotalCount en DataServiceQuery.
La propiedad GetContinuation: devuelve un objeto DataServiceQueryContinuation que contiene el
URI de la siguiente pgina de resultados.
De forma predeterminada, WCF Data Services solo devuelve los datos seleccionados explcitamente por el
URI de la consulta. De esta forma, puede cargar explcitamente datos desde el servicio de datos cuando sea
necesario. Se enva una solicitud al servicio de datos cada vez que carga datos explcitamente desde el
servicio de datos. Los datos que se pueden cargar explcitamente incluyen entidades relacionadas, datos de
respuesta paginados y flujos de datos binarios.
Nota:
Puesto que un servicio de datos puede devolver una respuesta paginada, se recomienda que la aplicacin
use el modelo de programacin para controlar la respuesta paginada de un servicio de datos.
La cantidad de datos devueltos por una consulta tambin se puede reducir especificando que solo se
devuelvan algunas propiedades de una entidad en la respuesta.

Obtener un recuento del nmero total de entidades del conjunto


En algunos escenarios, es til saber el nmero total de entidades de una entidad establecida y no solamente
el nmero devuelto por la consulta. Llame al mtodo IncludeTotalCount de DataServiceQuery para
solicitar que se incluya este recuento total de entidades con los resultados de la consulta. En este caso, la
propiedad TotalCount del objeto QueryOperationResponse devuelto devuelve el nmero total de
entidades del conjunto.

MCT: Luis Dueas

Pag 71 de 128

WCF Data Service


Adems, puede obtener el recuento total de entidades del conjunto como valor de las estructuras Int32 o
Int64 llamando a los mtodos Count o LongCount, respectivamente. Cuando se llama a estos mtodos, no
se devuelve ningn objeto QueryOperationResponse; solo se devuelve el valor de recuento.

5.2.1. Proyecciones de consultas


La proyeccin proporciona un mecanismo en Open Data Protocol (OData) para reducir la cantidad de datos
de la fuente devueltos por una consulta mediante la especificacin de que solo se devuelven algunas
propiedades de una entidad en la respuesta.
En este tema se describen la definicin de la proyeccin de una consulta, cules son los requisitos para los
tipos con entidad y sin ella, la realizacin de actualizaciones en los resultados proyectados, la creacin de
tipos proyectados y la enumeracin de algunas consideraciones de proyecciones.

Definir una proyeccin de consultas


Puede agregar una clusula de proyeccin a una consulta mediante la opcin de consulta $select en un URI
o mediante la clusula select (Select en Visual Basic) en una consulta LINQ. Los datos de la entidad
devueltos se pueden proyectar en tipos de entidad o tipos sin entidad en el cliente. Los ejemplos de este
tema muestran cmo usar la clusula select en una consulta LINQ.
Nota:
Se puede producir una prdida de datos en el servicio de datos cuando se guardan actualizaciones
efectuadas en tipos proyectados.

Requisitos para tipos con entidad y sin ella


Los tipos de entidad deben tener una o varias propiedades de entidad que constituyen la clave de la
entidad. Los tipos de entidad se definen en clientes de una de las siguientes formas:
Aplicando las clases DataServiceKeyAttribute o DataServiceEntityAttribute al tipo.
Cuando el tipo tiene una propiedad denominada ID.
Cuando el tipo tiene una propiedad denominada typeID, donde type es el nombre del tipo.
De forma predeterminada, cuando proyecte los resultados de la consulta en un tipo definido en el cliente,
las propiedades solicitadas en la proyeccin deben existir en el tipo de cliente. Sin embargo, cuando
especifica un valor de true para la propiedad IgnoreMissingProperties de la clase DataServiceContext, es
necesario que se produzcan las propiedades especificadas en la proyeccin en el tipo de cliente.

Realizar actualizaciones en los resultados proyectados


Cuando proyecte los resultados de la consulta en tipos de entidad en el cliente, la clase
DataServiceContext puede realizar el seguimiento de esos objetos con las actualizaciones que se van a
devolver al servicio de datos cuando se llame al mtodo SaveChanges. No obstante, las actualizaciones
efectuadas en datos proyectados en entidades sin tipo en el cliente no se pueden devolver al servicio de
datos. Esto se debe a que el servicio de datos no puede actualizar la entidad correcta en el origen de datos
sin ninguna clave que identifique la instancia de la entidad. Los tipos sin identidad no se adjunta a la clase
DataServiceContext.
Cuando una o varias propiedades de un tipo de entidad definido en el servicio de datos no se producen en
el tipo de cliente en el que se proyecta la entidad, las inserciones de nuevas entidades no contendrn estas
propiedades que faltan. En este caso, las actualizaciones realizadas en entidades existentes tampoco
incluirn estas propiedades que faltan. Cuando un valor existe para tal propiedad, la actualizacin la
restablece en el valor predeterminado de la propiedad, de la forma definida en el origen de datos.

Crear tipos proyectados


En el siguiente ejemplo se usa una consulta LINQ annima que proyecta propiedades de relacionadas con la
direccin del tipo Customers en un nuevo tipo CustomerAddress, que se define en el cliente y al que se le
puede dar el atributo de tipo de entidad:
' Define an anonymous LINQ query that projects the Customers type into
' a CustomerAddress type that contains only address properties.

MCT: Luis Dueas

Pag 72 de 128

WCF Data Service


Dim query = From c In context.Customers _
Where c.Country = "Germany" _
Select New CustomerAddress With { _
.CustomerID = c.CustomerID, _
.Address = c.Address, _
.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}

En este ejemplo, se usa el modelo de inicializador de objeto para crear una nueva instancia del tipo
CustmerAddress en vez de llamar a un constructor. No se admiten constructores cuando se realizan
proyecciones en tipos de entidad, pero se pueden usar al realizar proyecciones en tipos sin entidad y
annimos. Puesto que CustomerAddress es un tipo de entidad, los cambios se pueden efectuar en el
servicio de datos y devolvrselos a l.
Asimismo, los datos de tipo Customer se proyectan en una instancia del tipo de entidad CustomerAddress
en vez de en un tipo annimo. Se admiten las proyecciones en tipos annimos, pero los datos son de solo
lectura porque los tipos annimos se tratan como tipos sin entidad.
La configuracin de la enumeracin MergeOption de la clase DataServiceContext se usa para identificar la
resolucin durante la proyeccin de la consulta. Es decir, si una instancia del tipo Customer ya existe en la
clase DataServiceContext, una instancia de CustomerAddress con la misma identidad seguir las reglas de
resolucin de entidades establecidas por la enumeracin MergeOption.
En la siguiente tabla se describen los comportamientos cuando se proyectan resultados en tipos con
entidad y sin ella:
Tipo sin
Accin
Tipo con entidad
entidad
Crear una nueva instancia proyectada mediante inicializadores,
como en el ejemplo siguiente:
Dim query = From c In context.Customers _
Where c.Country = "Germany" _
Select New CustomerAddress With { _
.CustomerID = c.CustomerID, _
.Address = c.Address, _

Admitida

Admitida

Se inicia una clase


NotSupportedException.

Admitida

Se inicia una clase


NotSupportedException.

Admitida

.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}

Crear una nueva instancia proyectada con constructores, como


en el ejemplo siguiente:
Dim query = From c In context.Customers _
Where c.Country = "Germany" _
Select New CustomerAddress( _
c.CustomerID, _
c.Address, _
c.City, _
c.Region, _
c.PostalCode, _
c.Country)

Usar una proyeccin para transformar un valor de propiedad,


como en el ejemplo siguiente:
Dim query = From c In context.Customers _
Where c.Country = "Germany" _

MCT: Luis Dueas

Pag 73 de 128

WCF Data Service


Select New CustomerAddress With _
{.CustomerID = c.CustomerID, _
.Address = "Full address: " & c.Address & ", " & _
c.City & "," & c.Region & " " & c.PostalCode, _
.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}

Esta transformacin no la admiten los tipos de entidad porque


puede confundir y posiblemente sobrescribir los datos en el
origen de datos que pertenece a otra entidad.

Consideraciones sobre proyecciones


Se aplican las siguiente consideraciones adicionales cuando se define una proyeccin de consultas.
Cuando defina las fuentes personalizadas para el formato Atom, debe asegurarse de que se
incluyan todas las propiedades de entidad con asignaciones personalizadas en la proyeccin.
Cuando no se incluya ninguna propiedad de entidad asignada en la proyeccin, se puede producir
la prdida de datos.
Cuando se realicen inserciones en un tipo proyectado que no contenga todas las propiedades de la
entidad en el modelo de datos del servicio de datos, las propiedades no incluidas en la proyeccin
en el cliente se establecen en sus valores predeterminados.
Cuando se realicen actualizaciones en un tipo proyectado que no contenga todas las propiedades
de la entidad en el modelo de datos del servicio de datos, los valores existentes no incluidos en la
proyeccin en el cliente se sobrescribirn con valores predeterminados sin inicializar.
Cuando una proyeccin incluya una propiedad compleja, se debe devolver todo el objeto
complejo.
Cuando una proyeccin incluya una propiedad de navegacin, los objetos relacionados se cargan
implcitamente sin tener que llamar al mtodo Expand. No se admite el mtodo Expand para su
uso en una consulta proyectada.
Las consultas de proyecciones de consultas en el cliente se traducen para usar la opcin de
consulta $select en el URI de solicitud. Cuando se ejecute una consulta con proyeccin en una
versin previa de WCF Data Services que no admita la opcin de consulta $select, se devuelve un
error. Esto tambin puede ocurrir cuando se establece la propiedad MaxProtocolVersion de la clase
DataServiceBehavior para el servicio de datos en el valor de la enumeracin V1.

5.2.1.1. Cmo: Proyectar los resultados de una consulta


La proyeccin proporciona un mecanismo para reducir la cantidad de datos devueltos por una consulta
mediante la especificacin de que solo se devuelven algunas propiedades de una entidad en la respuesta.
Puede realizar proyecciones en los resultados de una consulta de WCF Data Services mediante la opcin de
consulta $select o mediante la clusula select (Select en Visual Basic) en una consulta LINQ.
En el ejemplo de este tema se usa el servicio de datos de ejemplo Northwind y las clases del servicio de
datos del cliente generadas automticamente. Se crean este servicio y las clases de datos del cliente al
completar el tutorial rpido del servicio de datos de WCF.

Ejemplo
En el siguiente ejemplo se muestra una consulta LINQ que proyecta entidades Customers en un nuevo tipo
CustomerAddress, que contiene solo las propiedades especficas de la direccin ms la propiedad de
identidad. Esta clase CustomerAddress se define en el cliente y recibe el atributo para que la biblioteca de
cliente pueda reconocerla como tipo de entidad.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)

MCT: Luis Dueas

Pag 74 de 128

WCF Data Service


' Define an anonymous LINQ query that projects the Customers type into
' a CustomerAddress type that contains only address properties.
Dim query = From c In context.Customers _
Where c.Country = "Germany" _
Select New CustomerAddress With { _
.CustomerID = c.CustomerID, _
.Address = c.Address, _
.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}
Try
' Enumerate over the query result, which is executed implicitly.
For Each item In query
' Modify the address and mark the object as updated.
item.Address += " #101"
context.UpdateObject(item)
' Write out the current values.
Console.WriteLine("Customer ID: {0} \r\nStreet: {1} " _
& "\r\nCity: {2} \r\nState: {3} \r\nZip Code: {4} \r\nCountry: {5}", _
item.CustomerID, item.Address, item.City, item.Region, _
item.PostalCode, item.Country)
Next
' Save changes to the data service.
context.SaveChanges()
Catch ex As DataServiceQueryException
Throw New ApplicationException( _
"An error occurred during query execution.", ex)
End Try

En el siguiente ejemplo se muestra una consulta LINQ que proyecta las entidades Customers devueltas en
un nuevo tipo CustomerAddressNonEntity, que contiene solo las propiedades especficas de la direccin y
no tiene propiedad de identidad. Esta clase CustomerAddressNonEntity se define en el cliente y no recibe
el atributo como tipo de entidad.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define an anonymous LINQ query that projects the Customers type into
' a CustomerAddress type that contains only address properties.
Dim query = From c In context.Customers _
Where c.Country = "Germany" _
Select New CustomerAddressNonEntity With _
{.CompanyName = c.CompanyName, _
.Address = c.Address, _
.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}
Try
' Enumerate over the query result, which is executed implicitly.
For Each item In query
item.Address += "Street"

MCT: Luis Dueas

Pag 75 de 128

WCF Data Service


Console.WriteLine("Company name: {0} \nStreet: {1} " _
& "\nCity: {2} \nState: {3} \nZip Code: {4} \nCountry: {5}", _
item.CompanyName, item.Address, item.City, item.Region, _
item.PostalCode, item.Country)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException( _
"An error occurred during query execution.", ex)
End Try

En el siguiente ejemplo se muestran las definiciones de los tipos


CustomerAddressCustomerAddressNonEntity usados en los ejemplos anteriores.
<DataServiceKey("CustomerID")> _
Partial Public Class CustomerAddress
Private _customerID As String
Private _address As String
Private _city As String
Private _region As String
Private _postalCode As String
Private _country As String
Public Property CustomerID() As String
Get
Return Me._customerID
End Get
Set(ByVal value As String)
Me._customerID = Value
End Set
End Property
Public Property Address() As String
Get
Return Me._address
End Get
Set(ByVal value As String)
Me._address = Value
End Set
End Property
Public Property City() As String
Get
Return Me._city
End Get
Set(ByVal value As String)
Me._city = Value
End Set
End Property
Public Property Region() As String
Get
Return Me._region
End Get
Set(ByVal value As String)
Me._region = Value
End Set
End Property

MCT: Luis Dueas

Pag 76 de 128

WCF Data Service


Public Property PostalCode() As String
Get
Return Me._postalCode
End Get
Set(ByVal value As String)
Me._postalCode = Value
End Set
End Property
Public Property Country() As String
Get
Return Me._country
End Get
Set(ByVal value As String)
Me._country = value
End Set
End Property
End Class
Public Class CustomerAddressNonEntity
Private _companyName As String
Private _address As String
Private _city As String
Private _region As String
Private _postalCode As String
Private _country As String
Public Property CompanyName() As String
Get
Return Me._companyName
End Get
Set(ByVal value As String)
Me._companyName = value
End Set
End Property
Public Property Address() As String
Get
Return Me._address
End Get
Set(ByVal value As String)
Me._address = Value
End Set
End Property
Public Property City() As String
Get
Return Me._city
End Get
Set(ByVal value As String)
Me._city = Value
End Set
End Property
Public Property Region() As String
Get
Return Me._region
End Get

MCT: Luis Dueas

Pag 77 de 128

WCF Data Service


Set(ByVal value As String)
Me._region = Value
End Set
End Property
Public Property PostalCode() As String
Get
Return Me._postalCode
End Get
Set(ByVal value As String)
Me._postalCode = Value
End Set
End Property
Public Property Country() As String
Get
Return Me._country
End Get
Set(ByVal value As String)
Me._country = value
End Set
End Property
End Class

5.2.2. Consideraciones sobre LINQ


En este tema se proporciona informacin sobre la forma en la que se redactan y se ejecutan las consultas
LINQ cuando se usa el cliente de WCF Data Services y las limitaciones de uso de LINQ para consultar un
servicio de datos que implemente Open Data Protocol (OData) .

Redactar consultas LINQ


LINQ permite redactar consultas en una coleccin de objetos que implemente la interfaz IEnumerable. Tanto
el cuadro de dilogo Agregar referencia de servicio de Visual Studio como la herramienta DataSvcUtil.exe
se usan para generar una representacin de un servicio de OData como clase de contendor de entidades
que hereda de la clase DataServiceContext, as como objetos que representen las entidades devueltas en
fuentes. Estas herramientas tambin generan propiedades en la clase de contenedor de entidades de las
colecciones que el servicio exponen como fuentes. Cada una de estas propiedades de la clase que
encapsula el servicio de datos devuelve una clase DataServiceQuery. Puesto que la clase DataServiceQuery
implementa la interfaz IQueryable definida por LINQ, WCF Data Services puede redactar una consulta LINQ
en las fuentes expuestas por el servicio de datos, que traduce la biblioteca cliente en un URI de solicitud de
consulta que se enva al servicio de datos en ejecucin.
Nota:
El conjunto de consultas que se pueden expresar en la sintaxis de LINQ es ms amplio que los habilitados
en la sintaxis URI basada en OData que usan los servicios de datos. Se produce una excepcin
NotSupportedException cuando la consulta no puede asignarse a un URI del servicio de datos de destino.
El siguiente ejemplo es una consulta LINQ que devuelve Orders con un costo de flete de ms de 30 $ y
ordena los resultados por la fecha de envo, comenzando por la fecha de envo ms reciente:
Dim selectedOrders = From o In context.Orders _
Where (o.Freight > 30) _
Order By o.ShippedDate Descending _
Select o

Esta consulta LINQ se traduce en el siguiente URI de la consulta que se ejecuta en el servicio de base de
datos del tutorial rpido basado en Northwind:

http://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30
MCT: Luis Dueas

Pag 78 de 128

WCF Data Service


LINQ permite redactar consultas mediante el uso tanto de la sintaxis de consulta declarativa especfica del
lenguaje, mostrada en el ejemplo anterior, como de un conjunto de mtodos de consulta denominados
operadores de consulta estndar. Una consulta equivalente al ejemplo anterior se puede redactar mediante
el uso de la sintaxis basada en mtodos nicamente, como se muestra en el siguiente ejemplo:
Dim selectedOrders = context.Orders _
.Where(Function(o) o.Freight.Value > 30) _
.OrderByDescending(Function(o) o.ShippedDate)

El cliente de WCF Data Services puede traducir ambos tipos de consultas redactadas en un URI de la
consulta y puede ampliar una consulta LINQ si anexa los mtodos de consulta a una expresin de consulta.
Cuando redacte consultas LINQ anexando la sintaxis del mtodo a una expresin de consulta o a una clase
DataServiceQuery, las operaciones se agregan al URI de la consulta en el orden en el que se llama a los
mtodos. Esto es equivalente a llamar al mtodo AddQueryOption para agregar cada opcin de consulta al
URI de la consulta.

Ejecutar consultas LINQ


Ciertos mtodos de consulta LINQ, como los mtodos First o Single, cuando se anexan a la consulta,
provocan la ejecucin de esta. Tambin se ejecuta una consult6a cuando los resultados se enumeran
implcitamente, como durante un bucle foreach o cuando la consulta se asigna a una coleccin List.
El cliente ejecuta una consulta LINQ en dos partes. Siempre que sea posible, las expresiones LINQ de una
consulta primero se evalan en el cliente y, a continuacin, se generan y se envan al servicio de datos para
su evaluacin en los datos del servicio.
Cuando no se puede traducir ninguna consulta LINQ de un URI de consulta conforme a OData , se produce
una excepcin al intentar la ejecucin.

Ejemplos de consultas LINQ


Los ejemplos de las secciones siguientes muestran los tipos de consultas LINQ que se pueden ejecutar en
un servicio de OData .

Filtrar
Los ejemplos de consultas LINQ de esta seccin filtran los datos de la fuente devuelta por el servicio.
Los siguientes ejemplos son consultas equivalentes que filtran las entidades Orders devueltas para que solo
se devuelvan los pedidos con un costo de flete mayor que 30 $:
Usar sintaxis de consulta LINQ:
Dim filteredOrders = From o In context.Orders
Where o.Freight.Value > 30
Select o

Usar mtodos de consulta LINQ:


Dim filteredOrders = context.Orders.Where(Function(o) o.Freight.Value > 0)

La opcin $filter de la cadena de consulta del URI:

' Define a query for orders with a Freight value greater than 30.
Dim filteredOrders = context.Orders.AddQueryOption("$filter", "Freight gt 30M")

Todos los ejemplos anteriores se traducen en el URI de la consulta:

http://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M .

Ordenar
Los siguientes ejemplos muestran consultas equivalentes que ordenan ascendentemente los datos tanto por
nombre de compaa como por cdigo postal:
Usar sintaxis de consulta LINQ:
Dim sortedCustomers = From c In context.Customers
Order By c.CompanyName Ascending,
c.PostalCode Descending

MCT: Luis Dueas

Pag 79 de 128

WCF Data Service


Select c

Usar mtodos de consulta LINQ:


Dim sortedCustomers = context.Customers.OrderBy(Function(c) c.CompanyName) _
.ThenByDescending(Function(c) c.PostalCode)

Opcin $orderby de la cadena de consulta del URI):


Dim sortedCustomers = context.Customers.AddQueryOption("$orderby", "CompanyName, PostalCode desc")

Todos los ejemplos anteriores se traducen en el URI de la consulta:

http://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc .

Proyeccin
Los siguientes ejemplos muestran las consultas equivalentes que proyectan los datos devueltos en el tipo

CustomerAddress ms restringido:
Usar sintaxis de consulta LINQ:
Dim projectedQuery = From c In context.Customers
Select New CustomerAddress With
{
.CustomerID = c.CustomerID,
.Address = c.Address,
.City = c.City,
.Region = c.Region,
.PostalCode = c.PostalCode,
.Country = c.Country
}

Usar mtodos de consulta LINQ:


Dim projectedQuery = context.Customers.Where(Function(c) c.Country = "Germany") _
.Select(Function(c) New CustomerAddress With
{
.CustomerID = c.CustomerID,
.Address = c.Address,
.City = c.City,
.Region = c.Region,
.PostalCode = c.PostalCode,
.Country = c.Country
})

Nota:
La opcin de consulta $select no se puede agregar a ningn URI de la consulta mediante el uso del mtodo
AddQueryOption. Se recomienda usar el mtodo Select de LINQ para que el cliente genere la opcin de
consulta $select en el URI de solicitud.
Los dos ejemplos anteriores se traducen en el URI de la consulta:

"http://localhost:12345/northwind.svc/Customers()?$filter=Country eq
'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country" .

Paginacin del cliente


En los siguientes ejemplos se muestran las consultas equivalentes que solicita una pgina de las entidades
de pedidos ordenados que incluye 25 pedidos, omitiendo los 50 primeros pedidos:

Aplicar mtodos de consulta a una consulta LINQ:


Dim pagedOrders = (From o In context.Orders
Order By o.OrderDate Descending
Select o) _

MCT: Luis Dueas

Pag 80 de 128

WCF Data Service


.Skip(50).Take(25)

opciones $skip y $top de cadena de consulta de URI):


Dim pagedOrders = context.Orders _
.AddQueryOption("$orderby", "OrderDate desc") _
.AddQueryOption("$skip", 50) _
.AddQueryOption("$top", 25) _

Los dos ejemplos anteriores se traducen en el URI de la consulta:

http://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25 .

Expandir
Cuando se carga un servicio de datos de OData , puede solicitar que las entidades relacionadas con la
entidad que sea el destino de la consulta se incluyan en la fuente devuelta. Se llama al mtodo Expand en la
clase DataServiceQuery para el conjunto de entidades que sean el destino de la consulta LINQ, con el
nombre del conjunto de entidades relacionado proporcionado como el parmetro path.
En los siguientes ejemplos se muestran las formas equivalentes de usar el mtodo Expand en una consulta:
En la sintaxis de las consultas LINQ:
Dim ordersQuery = From o In context.Orders.Expand("Order_Details")
Where o.CustomerID = "ALFKI"
Select o

Con los mtodos de consulta LINQ:


Dim ordersQuery = context.Orders.Expand("Order_Details") _
.Where(Function(o) o.CustomerID = "ALFKI")

Los dos ejemplos anteriores se traducen en el URI de la consulta:

http://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details .

Mtodos LINQ no admitidos


La siguiente tabla contiene las clases de mtodos LINQ que no se admiten y que no se pueden incluir en
una consulta ejecutada en un servicio de OData :
Tipo de operacin

Mtodos no admitidos
No se admite ningn operador de conjuntos en una clase DataServiceQuery, que
incluya lo siguiente:
All
Any
Concat

Operadores de
conjuntos

DefaultIfEmpty
Distinct
Except
Intersect
Union
Zip

Operaciones de
ordenacin

No se admiten los siguientes operadores de ordenacin que requieran la interfaz


IComparer en una clase DataServiceQuery:
OrderBy
OrderByDescending

MCT: Luis Dueas

Pag 81 de 128

WCF Data Service


ThenBy
ThenByDescending
No se admiten ninguno de los siguientes operadores de proyeccin y filtrado que
acepten un argumento posicional en una clase DataServiceQuery:
Join
Select
Mtodos de
proyeccin y filtrado

SelectMany
SelectMany
SelectMany
SelectMany
Where
No se admite ningn operador de agrupacin en una clase DataServiceQuery, que
incluya lo siguiente:

Operadores de
agrupacin

GroupBy
GroupJoin
Los operadores de agrupacin se deben ejecutar en el cliente.
No se admite ninguna operacin de agregado en una clase DataServiceQuery, que
incluya lo siguiente:
Aggregate
Average
Count

Operadores de
agregacin

LongCount
Max
Min
Sum
Las operaciones de agregado se deben ejecutar en el cliente o las debe encapsular
una operacin de servicio.
No se admiten los siguientes operadores de paginacin en una clase
DataServiceQuery:
ElementAt
Last
LastOrDefault

Operadores de
paginacin

SkipWhile
TakeWhile
Nota:
Los operadores de paginacin que se ejecuten en una secuencia vaca devuelven
NULL.

Operadores

MCT: Luis Dueas

No se admiten los siguientes operadores adicionales en una clase DataServiceQuery:

Pag 82 de 128

WCF Data Service


adicionales

1.

Empty

2.

Range

3.

Repeat

4.

ToDictionary

5.

ToLookup

Funciones de expresin admitidas


Se admiten los siguientes mtodos y propiedades de Common Language Runtime (CLR) porque se pueden
traducir en una expresin de consulta para su inclusin en el URI de solicitud en un servicio de OData :
Miembro de la clase String
Funcin de OData admitida
Concat

string concat(string p0, string p1)

Contains

bool substringof(string p0, string p1)

EndsWith

bool endswith(string p0, string p1)

IndexOf

int indexof(string p0, string p1)

Length

int length(string p0)

Replace

string replace(string p0, string find, string replace)

Substring

string substring(string p0, int pos)

Substring

string substring(string p0, int pos, int length)

ToLower

string tolower(string p0)

ToUpper

string toupper(string p0)

Trim

string trim(string p0)

Miembro de la estructura DateTime1 Funcin de OData admitida


Day

int day(DateTime p0)

Hour

int hour(DateTime p0)

Minute

int minute(DateTime p0)

Month

int month(DateTime p0)

Second

int second(DateTime p0)

Year
int year(DateTime p0)
1
Las propiedades de fecha y hora equivalentes de la clase Microsoft.VisualBasic.DateAndTime, as como el
mtodo DatePart de Visual Basic tambin se admiten.
Miembro de la clase Math Funcin de OData admitida
Ceiling

decimal ceiling(decimal p0)

Ceiling

double ceiling(double p0)

Floor

decimal floor(decimal p0)

Floor

double floor(double p0)

Round

decimal round(decimal p0)

Round

double round(double p0)

Miembro de la clase Expression Funcin de OData admitida


TypeIs
bool isof(type p0)
Adems, el cliente quiz pueda evaluar las funciones CLR adicionales en el cliente. Se produce una
excepcin NotSupportedException para cualquier expresin que no se pueda evaluar en el cliente y que
no se pueda traducir en un URI de solicitud vlido para su evaluacin en el servidor.

5.2.3. Materializacin de objetos


Cuando use el cuadro de dilogo Agregar referencia de servicio para utilizar una fuente Open Data
Protocol (OData) en una aplicacin cliente basada en .NET Framework, se generarn clases equivalentes
para cada tipo de entidad en el modelo de datos expuesto por la fuente. Los datos de entidad devueltos

MCT: Luis Dueas

Pag 83 de 128

WCF Data Service


por una consulta se materializan en una instancia de una de estas clases de servicio de datos de cliente
generadas.
WCF Data Services tambin le permite definir sus propias clases de servicio de datos de cliente en lugar de
usar las clases de datos generadas por herramientas. De esta forma, puede usar sus propias clases de datos,
que tambin se conocen como clases de datos "tipos de objetos CLR antiguos sin formato" (POCO). Al usar
estos tipos de clases de datos personalizadas, debe asignar un atributo a la clase de datos con la clase
DataServiceKeyAttribute o la clase DataServiceEntityAttribute y asegurarse de que los nombres de tipos en
el cliente coincidan con los del modelo de datos del servicio de datos.
Despus de que la biblioteca recibe el mensaje de respuesta de la consulta, materializa los datos devueltos
desde la fuente OData en instancias de las clases del servicio de datos de cliente que tienen el tipo de la
consulta. El proceso general para materializar estos objetos es el siguiente:
1.

La biblioteca de cliente lee el tipo serializado desde el elemento entry en la fuente del mensaje de
respuesta e intenta crear una nueva instancia del tipo correcto de una de estas formas:

Cuando el tipo declarado en la fuente tenga el mismo nombre que el tipo de la clase
DataServiceQuery, se crea una nueva instancia de este tipo mediante el constructor vaco.

Cuando el tipo declarado en la fuente tenga el mismo tipo que se deriva del tipo de la
clase DataServiceQuery, se crea una nueva instancia de este tipo derivado mediante el
constructor vaco.

Cuando el tipo declarado en la fuente no se pueda hacer coincidir con el tipo de la clase
DataServiceQuery ni con ningn tipo derivado, se crea una nueva instancia del tipo
consultado mediante el constructor vaco.

Cuando se establezca la propiedad ResolveType, se llama al delegado proporcionado para


invalidar la asignacin de tipos basada en nombre predeterminada y, en su lugar, se crea
una nueva instancia del tipo devuelto por el delgado Func. Si este delegado devuelve un
valor NULL, en su lugar se crea una nueva instancia del tipo consultado. Quiz sea
necesario invalidar la asignacin de nombre basada en tipo predeterminada para admitir
escenarios de herencia.

2.

La biblioteca de cliente lee el valor de URI desde el elemento id de entry, que es el valor de
identidad de la entidad. A menos que se use un valor de la propiedad MergeOption de la
enumeracin NoTracking, se usa el valor de identidad para realizar el seguimiento del objeto en la
clase DataServiceContext. El valor de identidad tambin se usa para garantizar que solo se cree una
nica instancia de identidad, aunque se devuelva varias veces una entidad en la respuesta de la
consulta.

3.

La biblioteca de cliente lee propiedades desde la entrada de la fuente y establece las propiedades
correspondientes en el objeto recin creado. Cuando un objeto con el mismo valor de identidad se
produce en la clase DataServiceContext, las propiedades se establecen basndose en la
configuracin de MergeOption de la clase DataServiceContext. Puede que la respuesta contenga
valores de propiedad para los que no se produzca ninguna propiedad correspondiente en el tipo
de cliente. En este caso, la accin depende del valor de la propiedad IgnoreMissingProperties de la
clase DataServiceContext. Cuando esta propiedad se establece en true, se ignora la propiedad
que falta. En caso contrario, se produce un error. Las propiedades se establecen de la siguiente
forma:

Las propiedades escalares se establecen en el valor correspondiente de la entrada del


mensaje de respuesta.

Las propiedades complejas se establecen en una nueva instancia de tipo complejo, que se
establecen con las propiedades del tipo complejo de la respuesta.

MCT: Luis Dueas

Pag 84 de 128

WCF Data Service


o

Las propiedades de navegacin que devuelven una coleccin de entidades relacionadas se


establecen en una instancia nueva o en una instancia existente de la interfaz ICollection,
donde T es el tipo de entidad relacionada. Esta coleccin est vaca a menos que se hayan
cargado los objetos relacionados en la clase DataServiceContext.
Nota:
Cuando las clases de datos del cliente generadas admitan el enlace de datos, las
propiedades de navegacin devuelven instancias de la clase DataServiceCollection en su
lugar.

4.

Se genera el evento ReadingEntity.

5.

La biblioteca de clientes adjunta el objeto a la clase DataServiceContext. El objeto no se adjunta


cuando la clase MergeOption es la enumeracin NoTracking.

5.2.4. Cmo: Ejecutar consultas en el servicio de datos


WCF Data Services le permite consultar un servicio datos desde una aplicacin cliente basada en .NET
Framework usando las clases generadas del servicio de datos del cliente. Puede ejecutar las consultas
usando uno de estos mtodos:
Ejecutar una consulta LINQ en la instancia con nombre de DataServiceQuery que se obtiene desde
la instancia de DataServiceContext generada por la herramienta Add Data Service Reference.
Implcitamente, enumerando en la instancia con nombre de DataServiceQuery que se obtiene
desde la instancia de DataServiceContext generada por la herramienta Add Data Service
Reference.
Explcitamente, llamando al mtodo Execute de DataServiceQuery o al mtodo BeginExecute para
la ejecucin asincrnica.
En el ejemplo de este tema se usa el servicio de datos de ejemplo Northwind y las clases del servicio de
datos del cliente generadas automticamente. Se crean este servicio y las clases de datos del cliente al
completar el tutorial rpido de WCF Data Services.

Ejemplo
En el ejemplo siguiente se muestra cmo definir y ejecutar en el servicio de datos de Northwind una
consulta LINQ que devuelve todas las entidades Customers.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Define a LINQ query that returns all customers.
Dim allCustomers = From cust In context.Customers Select cust
' Enumerate over the query obtained from the context.
For Each customer As Customer In allCustomers
Console.WriteLine("Customer Name: {0}", customer.CompanyName)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el siguiente ejemplo se muestra cmo usar el contexto que genera la herramienta Add Data Service
Reference para ejecutar implcitamente en el servicio de datos de Northwind una consulta que devuelve

MCT: Luis Dueas

Pag 85 de 128

WCF Data Service


todas las entidades Customers. El contexto determina automticamente el URI del conjunto de entidades

Customers solicitado. La consulta se ejecuta implcitamente cuando se produce la enumeracin.


' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a new query for Customers.
Dim query As DataServiceQuery(Of Customer) = context.Customers
Try
' Enumerate over the query result, which is executed implicitly.
For Each customer As Customer In query
Console.WriteLine("Customer Name: {0}", customer.CompanyName)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el ejemplo siguiente se muestra cmo usar DataServiceContext para ejecutar explcitamente en el


servicio de datos de Northwind una consulta que devuelve todas las entidades Customers.
' Define a request URI that returns Customers.
Dim customersUri = New Uri(svcUri, "Northwind.svc/Customers")
' Create the DataServiceContext using the service URI.
Dim context = New DataServiceContext(svcUri)
Try
' Enumerate over the query result.
For Each customer As Customer In context.Execute(Of Customer)(customersUri)
Console.WriteLine("Customer Name: {0}", customer.CompanyName)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

5.2.5. Cmo: Agregar opciones de consulta a una consulta de


servicio de datos
WCF Data Services le permite consultar un servicio datos desde una aplicacin cliente basada en .NET
Framework usando las clases generadas del servicio de datos del cliente. La forma ms fcil de hacerlo es
crear una expresin de consulta Language Integrated Query (LINQ) que incluya las opciones de consulta
deseadas. Adems, puede llamar a una serie de mtodos de consulta LINQ para crear una consulta
equivalente. Por ltimo, puede usar el mtodo AddQueryOption para agregar las opciones de consulta a
una consulta. En cada uno de estos casos, el URI que genera el cliente incluye el conjunto de entidades
solicitado con las opciones de consulta seleccionadas aplicadas.

Ejemplo
En el ejemplo siguiente se muestra cmo crear una expresin de consulta LINQ que devuelve solo los
pedidos con un coste de flete superior a 30 dlares y que ordena los resultados por la fecha de envo en
orden descendente.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders = From o In context.Orders Where (o.Freight > 30) Order By o.ShippedDate Descending Select o
Try
' Enumerate over the results of the query.

MCT: Luis Dueas

Pag 86 de 128

WCF Data Service


For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Ship Date: {1} - Freight: {2}", order.OrderID, order.ShippedDate, order.Freight)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el ejemplo siguiente se muestra cmo crear un consulta LINQ, mediante los mtodos de consulta LINQ,
que es equivalente a la consulta anterior.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders = context.Orders.Where(Function(o) o.Freight.Value > 30).OrderByDescending(Function(o) o.ShippedDate)
Try
' Enumerate over the results of the query.
For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Ship Date: {1} - Freight: {2}", order.OrderID, order.ShippedDate, order.Freight)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el siguiente ejemplo se muestra cmo usar el mtodo AddQueryOption para crear una clase
DataServiceQuery que es equivalente a los ejemplos anteriores.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = context.Orders _
.AddQueryOption("$filter", "Freight gt 30") _
.AddQueryOption("$orderby", "OrderID desc")
Try
' Enumerate over the results of the query.
For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Ship Date: {1} - Freight: {2}", order.OrderID, order.ShippedDate, order.Freight)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el ejemplo siguiente se muestra cmo usar la opcin de consulta $orderby para filtrar y ordenar los
objetos Orders devueltos por la propiedad Freight.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' that also orders the result by the Freight value, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = context.Orders.AddQueryOption("$orderby", "Freight gt 30 desc")
Try
' Enumerate over the results of the query.
For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Freight: {1}", order.OrderID, order.Freight)
Next

MCT: Luis Dueas

Pag 87 de 128

WCF Data Service


Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

5.2.6. Cmo: Determinar el nmero de entidades devueltas por una


consulta
Con WCF Data Services , puede determinar el nmero de entidades que existen en el conjunto de entidades
especificado por un URI de consulta. Este nmero se puede incluir junto con el resultado de la bsqueda o
como valor entero.

Ejemplo
En este ejemplo se ejecuta una consulta despus de llamar al mtodo IncludeTotalCount. La propiedad
TotalCount devuelve el nmero de entidades del conjunto de entidades Customers.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a new query for Customers that includes the total count.
Dim query As DataServiceQuery(Of Customer) = context.Customers.IncludeTotalCount()
Try
' Execute the query for all customers and get the response object.
Dim response As QueryOperationResponse(Of Customer) = _
CType(query.Execute(), QueryOperationResponse(Of Customer))
' Retrieve the total count from the response.
Console.WriteLine("There are a total of {0} customers.", response.TotalCount)
' Enumerate the customers in the response.
For Each customer As Customer In response
Console.WriteLine("\tCustomer Name: {0}", customer.CompanyName)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En este ejemplo se llama al mtodo Count para devolver nicamente un valor entero que es el nmero de
entidades del conjunto de entidades Customers.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a new query for Customers.
Dim query As DataServiceQuery(Of Customer) = context.Customers
Try
' Execute the query to just return the value of all customers in the set.
Dim totalCount = query.Count()
' Retrieve the total count from the response.
Console.WriteLine("There are {0} customers in total.", totalCount)
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

5.2.7. Cmo: especificar las credenciales de cliente para una


solicitud de servicio de datos
De forma predeterminada, la biblioteca cliente no proporciona credenciales cuando se enva una solicitud a
un servicio OData . Sin embargo, puede especificar que las credenciales se enven para autenticar solicitudes

MCT: Luis Dueas

Pag 88 de 128

WCF Data Service


al servicio de datos proporcionando una clase NetworkCredential para la propiedad Credentials de la clase
DataServiceContext. En el ejemplo de este tema se muestra cmo proporcionar explcitamente credenciales
que el cliente de WCF Data Services use cuando solicite datos del servicio de datos.

Ejemplo
El siguiente ejemplo proviene una pgina de cdigo subyacente de un archivo de lenguaje XAML que es la
pgina principal de la aplicacin de Windows Presentation Framework. En este ejemplo se muestra una
instancia de LoginWindow para recopilar las credenciales de autenticacin del usuario y, a continuacin, las
usa cuando realiza una solicitud al servicio de datos.
Imports NorthwindClient.Northwind
Imports System.Data.Services.Client
Imports System.Windows.Data
Imports System.Net
Imports System.Windows
Imports System.Security
Partial Public Class ClientCredentials
Inherits Window
' Create the binding collections and the data service context.
Private binding As DataServiceCollection(Of Customer)
Private context As NorthwindEntities
Private customerAddressViewSource As CollectionViewSource
' Instantiate the service URI and credentials.
Dim serviceUri As Uri = New Uri("http://localhost:54321/Northwind.svc/")
Private credentials As NetworkCredential = New NetworkCredential()
Public Sub Main()
InitializeComponent()
End Sub
Private Sub ClientCredentials_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim userName = String.Empty
Dim domain = String.Empty
Dim password = New SecureString()
' Get credentials for authentication.
Dim login As New LoginWindow()
login.ShowDialog()
If login.DialogResult = True _
AndAlso Not login.userNameBox.Text Is String.Empty _
AndAlso login.passwordBox.SecurePassword.Length <> 0 Then
' Instantiate the context.
context = New NorthwindEntities(serviceUri)
' Get the user name and domain from the login.
Dim qualifiedUserName As String() = login.userNameBox.Text.Split(New [Char]() {"\"c})
If qualifiedUserName.Length = 2 Then
domain = qualifiedUserName(0)
userName = qualifiedUserName(1)
Else
userName = login.userNameBox.Text
End If
password = login.passwordBox.SecurePassword
' Set the client authentication credentials.
context.Credentials = _
New NetworkCredential(userName, password, domain)
' Define an anonymous LINQ query that returns a collection of Customer types.

MCT: Luis Dueas

Pag 89 de 128

WCF Data Service


Dim query = From c In context.Customers Where c.Country = "Germany" Select c
Try
' Instantiate the binding collection, which executes the query.
binding = New DataServiceCollection(Of Customer)(query)
' Load result pages into the binding collection.
While Not binding.Continuation Is Nothing
' Continue to execute the query until all pages are loaded.
binding.Load(context.Execute(Of Customer)(binding.Continuation.NextLinkUri))
End While
' Assign the binding collection to the CollectionViewSource.
customerAddressViewSource = CType(Me.Resources("customerViewSource"), CollectionViewSource)
customerAddressViewSource.Source = binding
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
ElseIf login.DialogResult = False Then
MessageBox.Show("Login cancelled.")
End If
End Sub
End Class

El cdigo XAML siguiente define la pgina principal de la aplicacin WPF.


<Window x:Class="ClientCredentials"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="312" d:DesignWidth="577"
Loaded="ClientCredentials_Loaded">
<Window.Resources>
<CollectionViewSource x:Key="customerViewSource" />
</Window.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="" Height="312" Width="577"
VerticalAlignment="Top" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="203*" />
<RowDefinition Height="119*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="336*" />
</Grid.ColumnDefinitions>
<DataGrid AutoGenerateColumns="False" Height="213" HorizontalAlignment="Left"
ItemsSource="{Binding Source={StaticResource customerViewSource}}"
Name="customerDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected"
VerticalAlignment="Top" Width="553" Margin="12,44,0,0"
Grid.RowSpan="2" Grid.ColumnSpan="1">
<DataGrid.Columns>
<DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding Path=CustomerID}"
Header="Customer" Width="80" />
<DataGridTextColumn x:Name="addressColumn" Binding="{Binding Path=Address}"
Header="Address" Width="180" />

MCT: Luis Dueas

Pag 90 de 128

WCF Data Service


<DataGridTextColumn x:Name="cityColumn" Binding="{Binding Path=City}"
Header="City" Width="120" />
<DataGridTextColumn x:Name="countryColumn" Binding="{Binding Path=Country}"
Header="Country" Width="80" />
<DataGridTextColumn x:Name="postalCodeColumn" Binding="{Binding Path=PostalCode}"
Header="Postal Code" Width="90" />
<DataGridTextColumn Binding="{Binding Path=CompanyName}" Header="CompanyName" />
<DataGridTextColumn Binding="{Binding Path=ContactName}" Header="ContactName" />
<DataGridTextColumn Binding="{Binding Path=Phone}" Header="Phone" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Row="0" Grid.Column="0" Height="26" HorizontalAlignment="Left" Margin="16,12,0,0"
Name="serviceUriLabel" VerticalAlignment="Top" Width="550" />
</Grid>
</Window>

El siguiente ejemplo proviene de la pgina de cdigo subyacente de la ventana que se usa para recopilar las
credenciales de autenticacin del usuario antes de realizar una solicitud al servicio de datos.
Imports System.ComponentModel
Imports System.Windows
Imports System.Security
Partial Public Class LoginWindow
Inherits Window
Public Sub New()
InitializeComponent()
End Sub
Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click
Me.DialogResult = True
e.Handled = True
End Sub
Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click
Me.DialogResult = False
e.Handled = True
End Sub
Private Sub LoginWindow_Closing(ByVal sender As System.Object, ByVal e As CancelEventArgs)
If Me.DialogResult = True AndAlso _
(Me.userNameBox.Text = String.Empty OrElse Me.passwordBox.SecurePassword.Length = 0) Then
e.Cancel = True
MessageBox.Show("Please enter name and password or click Cancel.")
End If
End Sub
End Class

El cdigo XAML siguiente define el inicio de sesin de la aplicacin WPF.


<Window x:Class="LoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="200"
Title="LoginWindow" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
Closing="LoginWindow_Closing">
<StackPanel Name="LayoutRoot" Orientation="Vertical" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal">

MCT: Luis Dueas

Pag 91 de 128

WCF Data Service


<TextBlock Height="25" HorizontalAlignment="Left" Margin="10,20,0,0" Name="userNameLabel"
VerticalAlignment="Top"
Width="80" Text="User name:"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,20,0,0" Name="userNameBox" VerticalAlignment="Top"
Width="150" Text="DOMAIN\login"/>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBlock Height="25" HorizontalAlignment="Left" Margin="10,20,0,0" Name="pwdLabel" Width="80"
Text="Password:"/>
<PasswordBox Height="23" HorizontalAlignment="Left" Margin="10,20,0,0" Name="passwordBox" Width="150" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Height="80" VerticalAlignment="Top">
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23"
HorizontalAlignment="Right" Margin="8" IsCancel="True" />
<Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23"
HorizontalAlignment="Right" Margin="8" IsDefault="True" />
</StackPanel>
</StackPanel>
</Window>

Seguridad
Las siguientes consideraciones de seguridad se aplican al ejemplo de este tema:
Para comprobar que funcionan las credenciales proporcionadas en este ejemplo, el servicio de
datos de Northwind debe usar un esquema de autenticacin que no sea de acceso annimo. De lo
contrario, el sitio web que hospede el servicio de datos no solicitar las credenciales.
Las credenciales de usuario solo se deben solicitar durante la ejecucin y no se deben almacenar en
la memoria cach. Las credenciales se deben almacenar siempre de forma segura.
Los datos enviados con la autenticacin bsica e implcita no se cifran. Por tanto, los datos los
puede ver un adversario. Adems, se envan credenciales de autenticacin bsica (nombre de
usuario y contrasea) en texto no cifrado y se pueden interceptar.

5.2.8. Cmo: establecer los encabezados en la solicitud de cliente


Cuando use la biblioteca cliente de WCF Data Services para acceder a un servicio de datos compatible con
Open Data Protocol (OData) , la biblioteca establece automticamente los encabezados HTTP necesarios en
los mensajes de solicitud enviados al servicio de datos. Sin embargo, la biblioteca cliente no sabe establecer
los encabezados de mensaje necesarios en ciertos casos, como cuando el servicio de datos necesita cookies
o autenticacin basada en notificaciones. En estos casos, debe establecer manualmente los encabezados de
mensaje del mensaje de solicitud antes de enviarlo. En el ejemplo de este tema se muestra cmo controla el
evento SendingRequest para agregar un nuevo encabezado al mensaje de solicitud antes de que se enve al
servicio de datos.
En el ejemplo de este tema se usa el servicio de datos de ejemplo Northwind y las clases del servicio de
datos de cliente generadas automticamente. Se crean este servicio y las clases de datos del cliente al
completar el tutorial rpido del servicio de datos de WCF. Adems puede usar el servicio de datos de
ejemplo Northwind que se publica en el sitio web de OData . Este servicio de datos de ejemplo es de solo
lectura y si se intentan guardar los cambios, devuelve un error. Los servicios de datos de ejemplo del sitio
web de OData permiten la autenticacin annima.

Ejemplo
En el siguiente ejemplo se registra un controlador del evento SendingRequest y, a continuacin, se ejecuta
una consulta en el servicio de datos.
Nota:
Cuando un servicio de datos necesita que se establezca manualmente el encabezado del mensaje de todas

MCT: Luis Dueas

Pag 92 de 128

WCF Data Service


las solicitudes, plantese registrar el controlador del evento SendingRequest mediante la invalidacin del
mtodo parcial OnContextCreated del contenedor de entidades que represente el servicio de datos, que
en este caso es NorthwindEntities.
' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri)
' Register to handle the SendingRequest event.
' Note: If this must be done for every request to the data service, consider
' registering for this event by overriding the OnContextCreated partial method in
' the entity container, in this case NorthwindEntities.
AddHandler context.SendingRequest, AddressOf OnSendingRequest
' Define a query for orders with a Freight value greater than 30.
Dim query = From cust In context.Customers Where cust.Country = "Germany" Select cust
Try
' Enumerate to execute the query.
For Each cust As Customer In query
Console.WriteLine("Name: {0}\nAddress:\n{1}\n{2}, {3}", _
cust.CompanyName, cust.Address, cust.City, cust.Region)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException( _
"An error occurred during query execution.", ex)
End Try

El siguiente mtodo controla el evento SendingRequest y agrega un encabezado de autenticacin a la


solicitud.
Private Shared Sub OnSendingRequest(ByVal sender As Object, ByVal e As SendingRequestEventArgs)
' Add an Authorization header that contains an OAuth WRAP access token to the request.
e.RequestHeaders.Add("Authorization", "WRAP access_token=""123456789""")
End Sub

5.3. Cargar contenido aplazado


De forma predeterminada, WCF Data Services limita el nmero de datos que devuelve una consulta. Sin
embargo, es posible cargar explcitamente datos adicionales, incluidos los datos de la respuesta paginados,
las entidades relacionadas y los flujos de datos binarios, del servicio de datos cuando sea necesario. En este
tema se describe cmo cargar dicho contenido aplazado en una aplicacin.

Entidades relacionadas
Cuando se ejecuta una consulta, solo se devuelven las entidades pertenecientes al conjunto de entidades
direccionado. Por ejemplo, cuando una consulta al servicio de datos de Northwind devuelve entidades

Customers, no se devuelven de forma predeterminada las entidades relacionadas Orders, aunque haya una
relacin entre Customers y Orders. Adems, cuando est habilitada la paginacin en el servicio de datos,
debe cargar explcitamente las pginas de datos subsiguientes del servicio. Hay dos maneras de cargar las
entidades relacionadas:
Carga diligente: puede usar la opcin de consulta $expand para solicitar que la consulta devuelva
entidades que estn relacionadas mediante una asociacin con el conjunto de entidades solicitado
por la consulta. Utilice el mtodo Expand en DataServiceQuery para agregar la opcin $expand a la
consulta que se enva al servicio de datos. Puede solicitar varios conjuntos de entidades
relacionados separndolos mediante comas, como muestra el ejemplo siguiente. Todas las

MCT: Luis Dueas

Pag 93 de 128

WCF Data Service


entidades solicitadas por la consulta se devuelven en una nica respuesta. En el ejemplo siguiente
se devuelve Order_Details y Customers junto con el conjunto de entidades Orders:
' Define a query for orders that also returns items and customers.
Dim query As DataServiceQuery(Of Order) = context.Orders.Expand("Order_Details,Customer")

WCF Data Services limita a 12 el nmero de conjuntos de entidades que se pueden incluir en una
nica consulta utilizando la opcin de consulta $expand.
Carga explcita: puede llamar al mtodo LoadProperty de la instancia de DataServiceContext para
cargar explcitamente las entidades relacionadas. Cada llamada al mtodo LoadProperty crea una
solicitud independiente al servicio de datos. En el ejemplo siguiente se carga explcitamente

Order_Details para una entidad Orders:


' Explicitly load the order details for each order.
context.LoadProperty(order, "Order_Details")

Al considerar qu opcin se debe usar, observe que hay una correlacin entre el nmero de solicitudes al
servicio de datos y la cantidad de datos devueltos en una sola respuesta. Use la carga diligente cuando su
aplicacin requiera objetos asociados y desee evitar la latencia agregada de las solicitudes adicionales para
recuperarlos explcitamente. Sin embargo, si hay casos en que la aplicacin solo necesita los datos para
determinadas instancias de entidades relacionadas, debera plantearse cargar explcitamente esas entidades
llamando al mtodo LoadProperty.

Contenido paginado
Si la paginacin est habilitada en el servicio de datos, la configuracin del servicio de datos limita el
nmero de entradas de la fuente que devuelve el servicio de datos. Los lmites de pgina pueden
establecerse por separado para cada conjunto de entidades. Si est habilitada la paginacin, la ltima
entrada de la fuente contiene un vnculo a la pgina de datos siguiente. Este vnculo est contenido en un
objeto DataServiceQueryContinuation. El URI a la pgina de datos siguiente se obtiene llamando al mtodo
GetContinuation del objeto QueryOperationResponse que se obtiene cuando se ejecuta DataServiceQuery.
A continuacin, el objeto DataServiceQueryContinuation devuelto se usa para cargar la pgina de
resultados siguiente. Debe enumerar los resultados de la consulta antes de llamar al mtodo
GetContinuation. Considere la posibilidad de usar un bucle dowhile para enumerar el resultado de la
consulta primero y, a continuacin, comprobar el valor de un vnculo siguiente non-null. Cuando el mtodo
GetContinuation devuelve null (Nothing en Visual Basic), no hay ninguna pgina de resultados adicional
para la consulta original. En el ejemplo siguiente se muestra un bucle dowhile que carga los datos del
cliente paginados del servicio de datos de ejemplo Northwind.
' With a paged response from the service, use a do...while loop
' to enumerate the results before getting the next link.
Do
' Write the page number.
Console.WriteLine("Page {0}:", pageCount + 1)
' If nextLink is not null, then there is a new page to load.
If token IsNot Nothing Then
' Load the new page from the next link URI.
response = CType(context.Execute(Of Customer)(token), QueryOperationResponse(Of Customer))
End If
' Enumerate the customers in the response.
For Each customer As Customer In response
Console.WriteLine("\tCustomer Name: {0}", customer.CompanyName)
Next
' Get the next link, and continue while there is a next link.
token = response.GetContinuation()
Loop While token IsNot Nothing

MCT: Luis Dueas

Pag 94 de 128

WCF Data Service


Cuando una consulta solicita que se devuelvan las entidades relacionadas en una respuesta nica junto con
el conjunto de entidades solicitado, los lmites de paginacin pueden afectar a las fuentes anidadas que
estn incluidas alineadas con la respuesta. Por ejemplo, cuando se establece un lmite de paginacin en el
servicio de datos de ejemplo Northwind para el conjunto de entidades Customers, tambin puede
establecerse un lmite de paginacin independiente para el conjunto de entidades Orders relacionado,
como en el ejemplo siguiente del archivo Northwind.svc.cs que define el servicio de datos de ejemplo
Northwind.
' Set page size defaults for the data service.
config.SetEntitySetPageSize("Orders", 20)
config.SetEntitySetPageSize("Order_Details", 50)
config.SetEntitySetPageSize("Products", 50)
' Paging requires v2 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion = System.Data.Services.Common.DataServiceProtocolVersion.V2

En este caso, debe implementar la paginacin para las dos fuentes de entidades, la de nivel superior,

Customers, y las anidadas, Orders. En el ejemplo siguiente se muestra el bucle while que se usa para
cargar las pginas de las entidades Orders relacionadas con una entidad Customers seleccionada.
While nextOrdersLink IsNot Nothing
For Each o As Order In c.Orders
' Print out the orders.
Console.WriteLine("\t\tOrderID: {0} - Freight: ${1}", o.OrderID, o.Freight)
Next
' Load the next page of Orders.
Dim ordersResponse = context.LoadProperty(c, "Orders", nextOrdersLink)
nextOrdersLink = ordersResponse.GetContinuation()
End While

Flujos de datos binarios


WCF Data Services le permite tener acceso a datos de objetos binarios grandes (BLOB) en forma de flujo de
datos. La transmisin por secuencias aplaza la carga de datos binarios hasta que se necesita, y el cliente
puede procesar estos datos ms eficazmente. Para aprovecharse de esta funcionalidad, el servicio de datos
debe implementar el proveedor IDataServiceStreamProvider. Cuando est habilitada la transmisin por
secuencias, los tipos de entidad se devuelven sin los datos binarios relacionados. En este caso, debe usar el
mtodo GetReadStream de la clase DataServiceContext para tener acceso al flujo de datos para los datos
binarios del servicio. De igual forma, use el mtodo SetSaveStream para agregar o cambiar los datos
binarios de una entidad como un flujo.

5.3.1. Cmo: Cargar entidades relacionadas


Cuando necesite cargar entidades asociadas en WCF Data Services , puede usar el mtodo LoadProperty de
la clase DataServiceContext. Tambin puede usar el mtodo Expand de DataServiceQuery para requerir que
las entidades relacionadas se carguen rpidamente en la misma respuesta a la consulta.

Ejemplo
En el ejemplo siguiente se muestra cmo cargar explcitamente la entidad Customer relacionada con cada
instancia de Orders devuelta.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Enumerate over the top 10 orders obtained from the context.
For Each order As Order In context.Orders.Take(10)
' Explicitly load the customer for each order.

MCT: Luis Dueas

Pag 95 de 128

WCF Data Service


context.LoadProperty(order, "Customer")
' Write out customer and order information.
Console.WriteLine("Customer: {0} - Order ID: {1}", order.Customer.CompanyName, order.OrderID)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En el ejemplo siguiente se muestra cmo usar el mtodo Expand para devolver las entidades Order Details
pertenecientes a las entidades Orders devueltas por la consulta.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders that also returns items and customers.
Dim query As DataServiceQuery(Of Order) = context.Orders.Expand("Order_Details,Customer")
Try
' Enumerate over the first 10 results of the query.
For Each order As Order In query.Take(10)
Console.WriteLine("Customer: {0}", order.Customer.CompanyName)
Console.WriteLine("Order ID: {0}", order.OrderID)
For Each item As Order_Detail In order.Order_Details
Console.WriteLine("\tProduct: {0} - Quantity: {1}", item.ProductID, item.Quantity)
Next
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

5.3.2. Cmo: Cargar resultados paginados


WCF Data Services permite que el servicio de datos limite el nmero de entidades que se devuelven en una
fuente de respuesta nica. Cuando esto sucede, la ltima entrada de la fuente contiene un vnculo a la
pgina siguiente de datos. El URI a la pgina de datos siguiente se obtiene llamando al mtodo
GetContinuation del objeto QueryOperationResponse, que se obtiene cuando se ejecuta DataServiceQuery.
A continuacin, el URI representado por este objeto se utiliza para cargar la pgina siguiente de resultados.

Ejemplo
En este ejemplo se usa un bucle dowhile para cargar las entidades Customers desde los resultados
paginados del servicio de datos.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Dim token As DataServiceQueryContinuation(Of Customer) = Nothing
Dim pageCount = 0
Try
' Execute the query for all customers and get the response object.
Dim response As QueryOperationResponse(Of Customer) = _
CType(context.Customers.Execute(), QueryOperationResponse(Of Customer))
' With a paged response from the service, use a do...while loop
' to enumerate the results before getting the next link.
Do
' Write the page number.
Console.WriteLine("Page {0}:", pageCount + 1)
' If nextLink is not null, then there is a new page to load.

MCT: Luis Dueas

Pag 96 de 128

WCF Data Service


If token IsNot Nothing Then
' Load the new page from the next link URI.
response = CType(context.Execute(Of Customer)(token), QueryOperationResponse(Of Customer))
End If
' Enumerate the customers in the response.
For Each customer As Customer In response
Console.WriteLine("\tCustomer Name: {0}", customer.CompanyName)
Next
' Get the next link, and continue while there is a next link.
token = response.GetContinuation()
Loop While token IsNot Nothing
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

En este ejemplo se devuelve las entidades Orders relacionadas con cada entidad Customers y se utiliza un
bucle dowhile para cargar pginas de entidades Customers y un bucle while anidado para cargar
pginas de entidades Orders relacionadas del servicio de datos.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Dim nextLink As DataServiceQueryContinuation(Of Customer) = Nothing
Dim pageCount = 0
Dim innerPageCount = 0
Try
' Execute the query for all customers and related orders,
' and get the response object.
Dim response = _
CType(context.Customers.AddQueryOption("$expand", "Orders") _
.Execute(), QueryOperationResponse(Of Customer))
' With a paged response from the service, use a do...while loop
' to enumerate the results before getting the next link.
Do
' Write the page number.
Console.WriteLine("Customers Page {0}:", ++pageCount)
' If nextLink is not null, then there is a new page to load.
If nextLink IsNot Nothing Then
' Load the new page from the next link URI.
response = CType(context.Execute(Of Customer)(nextLink), QueryOperationResponse(Of Customer))
End If
' Enumerate the customers in the response.
For Each c As Customer In response
Console.WriteLine("\tCustomer Name: {0}", c.CompanyName)
Console.WriteLine("\tOrders Page {0}:", innerPageCount + 1)
' Get the next link for the collection of related Orders.
Dim nextOrdersLink As DataServiceQueryContinuation(Of Order) = _
response.GetContinuation(c.Orders)
While nextOrdersLink IsNot Nothing
For Each o As Order In c.Orders
' Print out the orders.
Console.WriteLine("\t\tOrderID: {0} - Freight: ${1}", o.OrderID, o.Freight)
Next

MCT: Luis Dueas

Pag 97 de 128

WCF Data Service


' Load the next page of Orders.
Dim ordersResponse = context.LoadProperty(c, "Orders", nextOrdersLink)
nextOrdersLink = ordersResponse.GetContinuation()
End While
Next
' Get the next link, and continue while there is a next link.
nextLink = response.GetContinuation()
Loop While nextLink IsNot Nothing
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try

5.4. Actualizar el servicio de datos


Cuando se usa la biblioteca de cliente de WCF Data Services para usar una fuente de Open Data Protocol
(OData) , la biblioteca traduce las entradas de la fuente en instancias de clases del servicio de datos del
cliente. Se realiza el seguimiento de estas clases del servicio de datos mediante el uso de la clase
DataServiceContext a la que pertenece la clase DataServiceQuery. El cliente realiza el seguimiento de los
cambios en las entidades que se notifican utilizando mtodos de la clase DataServiceContext. Estos
mtodos permiten al cliente realizar el seguimiento de las entidades agregadas y eliminadas y tambin los
cambios que se realizan en los valores de propiedad o en las relaciones entre instancias de entidad. Estos
cambios se devuelven al servicio de datos como operaciones basadas en REST al llamar al mtodo
SaveChanges.
Nota:
Al utilizar una instancia de DataServiceCollection para enlazar los datos a los controles, los cambios
realizados en los datos del control enlazado se notifican automticamente a DataServiceContext.

Agregar, modificar y cambiar entidades


Cuando se usa el cuadro de dilogo Agregar referencia de servicio de Visual Studio para agregar una
referencia a una fuente de OData , cada una de las clases del servicio de datos de cliente resultante tiene un
mtodo esttico Create que toma un parmetro para cada propiedad de entidad que no admite valores
NULL. Puede usar este mtodo para crear instancias de clases de tipos de entidad, como en el ejemplo
siguiente:
' Create the new product.
Dim newProduct = Product.CreateProduct(0, "White Tea - loose", False)

Para agregar una instancia de entidad, llame al mtodo AddTo adecuado en la clase DataServiceContext
generada por el cuadro de dilogo Agregar referencia de servicio, como se muestra en el ejemplo
siguiente:
' Add the new product to the Products entity set.
context.AddToProducts(newProduct)

Esto agrega el objeto al contexto y al conjunto de entidades correcto. Tambin puede llamar al mtodo
AddObject, pero, en ese caso, debe proporcionar el nombre del conjunto de entidades. Si la entidad
agregada tiene una o varias relaciones con otras entidades, puede usar el mtodo AddRelatedObject o bien
uno de los mtodos anteriores y tambin definir esos vnculos explcitamente. Estas operaciones se explican
ms adelante en este tema.
Para modificar una instancia de una entidad existente, primero ejecute una consulta para esa entidad,
efecte los cambios deseados en sus propiedades y, a continuacin, llame al mtodo UpdateObject de la
instancia de DataServiceContext para indicar a la biblioteca cliente que debe enviar una actualizacin para
ese objeto, como se muestra en el ejemplo siguiente:
' Mark the customer as updated.
context.UpdateObject(customerToChange)

MCT: Luis Dueas

Pag 98 de 128

WCF Data Service


Para eliminar una instancia de una entidad, llame al mtodo DeleteObject de la instancia de la clase
DataServiceContext, como se muestra en el ejemplo siguiente:
' Mark the product for deletion.
context.DeleteObject(deletedProduct)

Adjuntar entidades
La biblioteca de clientes le permite guardar las actualizaciones que realiz en una entidad sin ejecutar
primero ninguna consulta para cargar la entidad en la instancia de la clase DataServiceContext. Use el
mtodo AttachTo para adjuntar un objeto existente a un conjunto de entidades concreto de la instancia de
DataServiceContext. Despus puede modificar el objeto y guardar los cambios en el servicio de datos. En
el ejemplo siguiente, se adjunta al contexto un objeto de cliente que se ha cambiado y, a continuacin, se
llama a UpdateObject para marcar el objeto adjunto como Modified antes de llamar a SaveChanges:
' Attach the existing customer to the context and mark it as updated.
context.AttachTo("Customers", customer)
context.UpdateObject(customer)
' Send updates to the data service.
context.SaveChanges()

Al adjuntar objetos deben tenerse en cuenta las consideraciones siguientes:


Un objeto se adjunta con el estado Unchanged.
Cuando se adjunta un objeto, no se adjuntan los objetos relacionados con el objeto adjunto.
No se puede adjuntar un objeto si el contexto ya est realizando el seguimiento de la entidad.
Se usa la sobrecarga del mtodo AttachTo que toma un parmetro etag cuando se adjunta un
objeto entidad que se recibi junto con un valor de eTag. Este valor de eTag se usa despus para
comprobar la simultaneidad cuando se guardan los cambios realizados en el objeto adjunto.

Crear y modificar vnculos de relacin


Cuando se agrega una nueva entidad usando el mtodo AddObject o el mtodo AddTo adecuado de la
clase DataServiceContext generada por el cuadro de dilogo Agregar referencia de servicio, no se define
automticamente ninguna relacin entre la nueva entidad y las entidades relacionadas.
Puede crear y cambiar las relaciones entre las instancias de las entidades y hacer que la biblioteca de cliente
refleje esos cambios en el servicio de datos. Las relaciones entre las entidades se definen como asociaciones
en el modelo y la clase DataServiceContext realiza el seguimiento de cada relacin como objeto de vnculo
en el contexto. WCF Data Services proporciona los siguientes mtodos en la clase DataServiceContext para
crear, modificar y eliminar estos vnculos:
Mtodo
Descripcin
Crea un nuevo vnculo entre dos objetos entidad relacionados. Llamar a este mtodo es
AddRelatedObject equivalente a llamar a los mtodos AddObject y AddLink tanto para crear el nuevo
objeto como para definir la relacin en un objeto existente.
AddLink

Crea un nuevo vnculo entre dos objetos entidad relacionados.

SetLink

Actualiza un vnculo existente entre dos objetos entidad relacionados. El mtodo SetLink
tambin se usa para eliminar vnculos con una cardinalidad de cero o uno a uno (0..1:1) y
de uno a uno (1:1). Para ello, puede establecer el objeto relacionado en null.

DeleteLink

Marca para su eliminacin un vnculo cuyo seguimiento lo est realizando el contexto


cuando se llame al mtodo SaveChanges. Use este mtodo cuando elimine un objeto
relacionado o cuando cambie una relacin eliminando primero el vnculo a un objeto
existente y luego agregando un vnculo al nuevo objeto relacionado.

AttachLink

Notifica al contexto la existencia de un vnculo entre dos objetos entidad. El contexto


supone que esta relacin ya existe en el servicio de datos y no intenta crear el vnculo
cuando se llama al mtodo SaveChanges. Use este mtodo cuando adjunte objetos a un
contexto y tambin necesite adjuntar el vnculo entre los dos. Si est definiendo una

MCT: Luis Dueas

Pag 99 de 128

WCF Data Service


nueva relacin, en su lugar debe usar el mtodo AddLink.
Deja de realizar el seguimiento del vnculo especificado en el contexto. Este mtodo se
usa para eliminar relaciones uno a varios (*:*). En vnculos de relacin con una
cardinalidad de uno, debe usar el mtodo SetLink en su lugar.
En el ejemplo siguiente se muestra la forma de usar el mtodo AddRelatedObject para agregar un nuevo
DetachLink

Order_Detail que se relacione con una entidad Orders existente. Dado que el seguimiento del nuevo
objeto Order_Details lo realiza la clase DataServiceContext, la relacin del objeto Order_Details
agregado a la entidad Products existente se define llamando al mtodo AddLink:
' Add the new item with a link to the related order.
context.AddRelatedObject(order, "Order_Details", newItem)
' Since the item is now tracked by the context,
' set just the link to the related product.
context.AddLink(selectedProduct, "Order_Details", newItem)

Mientras que el mtodo AddLink definen los vnculos que se deben crear en el servicio de datos, para que
estos vnculos se reflejen en los objetos que estn en el contexto, tambin debe establecer las propiedades
de navegacin en los propios objetos. En el ejemplo anterior, debe establecer las propiedades de
navegacin de la forma siguiente:
' Add the new order detail to the collection, and
' set the reference to the product.
order.Order_Details.Add(newItem)
newItem.Order = order
newItem.Product = selectedProduct

Guardar los cambios


El seguimiento de los cambios se realiza en la instancia de la clase DataServiceContext, pero los cambios
no se envan al servidor inmediatamente. Una vez que haya efectuado los cambios necesarios de una
actividad determinada, llame al mtodo SaveChanges para enviar todos los cambios al servicio de datos.
Tambin puede guardar cambios de forma asincrnica utilizando los mtodos BeginSaveChanges y
EndSaveChanges.

5.4.1. Cmo: Agregar, modificar y eliminar entidades


Con las bibliotecas de cliente de WCF Data Services , puede crear, actualizar y eliminar los datos de entidad
de un servicio de datos realizando las acciones equivalentes en los objetos en la clase DataServiceContext.

Ejemplo
En el siguiente ejemplo se crea una nueva instancia de objeto y, a continuacin, se llama al mtodo
AddObject de la clase DataServiceContext para crear el elemento en el contexto. Cuando se llama al
mtodo SaveChanges se enva un mensaje HTTP POST al servicio de datos.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Create the new product.
Dim newProduct = Product.CreateProduct(0, "White Tea - loose", False)
' Set property values.
newProduct.QuantityPerUnit = "120gm bags"
newProduct.ReorderLevel = 5
newProduct.UnitPrice = 5.2D
Try
' Add the new product to the Products entity set.
context.AddToProducts(newProduct)
' Send the insert to the data service.
context.SaveChanges()

MCT: Luis Dueas

Pag 100 de 128

WCF Data Service


Console.WriteLine("New product added with ID {0}.", newProduct.ProductID)
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)

En el siguiente ejemplo se recupera y modifica un objeto existente y, a continuacin, se llama al mtodo


UpdateObject en DataServiceContext para marcar el elemento en el contexto cuando se actualice. Cuando
se llama al mtodo SaveChanges se enva un mensaje HTTP MERGE al servicio de datos.
Dim customerId = "ALFKI"
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Get a customer to modify using the supplied ID.
Dim customerToChange = (From customer In context.Customers _
Where customer.CustomerID = customerId Select customer).Single()
' Change some property values.
customerToChange.CompanyName = "Alfreds Futterkiste"
customerToChange.ContactName = "Maria Anders"
customerToChange.ContactTitle = "Sales Representative"
Try
' Mark the customer as updated.
context.UpdateObject(customerToChange)
' Send the update to the data service.
context.SaveChanges()
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)
End Try

En el siguiente ejemplo se llama al mtodo DeleteObject en DataServiceContext para marcar el elemento


en el contexto cuando se elimine. Cuando se llama al mtodo SaveChanges se enva un mensaje HTTP
DELETE al servicio de datos.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Get the product to delete, by product ID.
Dim deletedProduct = (From product In context.Products _
Where product.ProductID = productID _
Select product).Single()
' Mark the product for deletion.
context.DeleteObject(deletedProduct)
' Send the delete to the data service.
context.SaveChanges()
' Handle the error that occurs when the delete operation fails,
' which can happen when there are entities with existing
' relationships to the product being deleted.
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)
End Try

En el ejemplo siguiente se crea una instancia de objeto nueva y, a continuacin, se llama al mtodo
AddRelatedObject en DataServiceContext para crear el elemento en el contexto junto con el vnculo al
pedido relacionado. Cuando se llama al mtodo SaveChanges se enva un mensaje HTTP POST al servicio
de datos.
Dim productId = 25
Dim customerId = "ALFKI"

MCT: Luis Dueas

Pag 101 de 128

WCF Data Service


Dim newItem As Order_Detail = Nothing
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Get the specific product.
Dim selectedProduct = (From product In context.Products Where product.ProductID = productId Select product).Single()
' Get the specific customer.
Dim cust = (From customer In context.Customers.Expand("Orders") _
Where customer.CustomerID = customerId Select customer).Single()
' Get the first order.
Dim order = cust.Orders.FirstOrDefault()
' Create a new order detail for the specific product.
newItem = Order_Detail.CreateOrder_Detail(order.OrderID, selectedProduct.ProductID, 10, 5, 0)
' Add the new item with a link to the related order.
context.AddRelatedObject(order, "Order_Details", newItem)
' Since the item is now tracked by the context, set just the link to the related product.
context.AddLink(selectedProduct, "Order_Details", newItem)
' Add the new order detail to the collection, and set the reference to the product.
order.Order_Details.Add(newItem)
newItem.Order = order
newItem.Product = selectedProduct
' Send the inserts to the data service.
context.SaveChanges()
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred when saving changes.", ex)
' Handle any errors that may occur during insert, such as a constraint violation.
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)

5.4.2. Cmo: Definir las relaciones de entidad


Al agregar una nueva entidad en WCF Data Services , las relaciones entre la nueva entidad y las entidades
relacionadas no se definen automticamente. Puede crear y cambiar las relaciones entre las instancias de las
entidades y hacer que la biblioteca de cliente refleje esos cambios en el servicio de datos.

Ejemplo
En el ejemplo siguiente se crea una instancia de objeto nueva y, a continuacin, se llama al mtodo
AddRelatedObject de la clase DataServiceContext para crear el elemento en el contexto junto con el vnculo
al pedido relacionado. Se enva un mensaje POST de HTTP al servicio de datos cuando se llama al mtodo
SaveChanges.
Dim productId = 25
Dim customerId = "ALFKI"
Dim newItem As Order_Detail = Nothing
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Get the specific product.
Dim selectedProduct = (From product In context.Products _
Where product.ProductID = productId _
Select product).Single()
' Get the specific customer.
Dim cust = (From customer In context.Customers.Expand("Orders") _

MCT: Luis Dueas

Pag 102 de 128

WCF Data Service


Where customer.CustomerID = customerId Select customer).Single()
' Get the first order.
Dim order = cust.Orders.FirstOrDefault()
' Create a new order detail for the specific product.
newItem = Order_Detail.CreateOrder_Detail( _
order.OrderID, selectedProduct.ProductID, 10, 5, 0)
' Add the new item with a link to the related order.
context.AddRelatedObject(order, "Order_Details", newItem)
' Since the item is now tracked by the context, set just the link to the related product.
context.AddLink(selectedProduct, "Order_Details", newItem)
' Add the new order detail to the collection, and set the reference to the product.
order.Order_Details.Add(newItem)
newItem.Order = order
newItem.Product = selectedProduct
' Send the inserts to the data service.
context.SaveChanges()
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred when saving changes.", ex)
' Handle any errors that may occur during insert, such as a constraint violation.
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)

En el ejemplo siguiente se muestra cmo utilizar el mtodo AddObject para agregar un objeto

Order_Details a un objeto Orders relacionado con una referencia a un objeto Products concreto. Los
mtodos AddLink y SetLink definen las relaciones. En este ejemplo, las propiedades de navegacin del
objeto Order_Details tambin se establecen explcitamente.
Dim productId = 25
Dim customerId = "ALFKI"
Dim newItem As Order_Detail = Nothing
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
Try
' Get the specific product.
Dim selectedProduct = (From product In context.Products Where product.ProductID = productId Select product).Single()
' Get the specific customer.
Dim cust = (From customer In context.Customers.Expand("Orders") _
Where customer.CustomerID = customerId Select customer).Single()
' Get the first order.
Dim order = cust.Orders.FirstOrDefault()
' Create a new order detail for the specific product.
newItem = Order_Detail.CreateOrder_Detail(order.OrderID, selectedProduct.ProductID, 10, 5, 0)
' Add the new order detail to the context.
context.AddToOrder_Details(newItem)
' Add links for the one-to-many relationships.
context.AddLink(order, "Order_Details", newItem)
context.AddLink(selectedProduct, "Order_Details", newItem)
' Add the new order detail to the collection, and set the reference to the product.
order.Order_Details.Add(newItem)
newItem.Product = selectedProduct
' Send the inserts to the data service.
context.SaveChanges()
Catch ex As DataServiceQueryException

MCT: Luis Dueas

Pag 103 de 128

WCF Data Service


Throw New ApplicationException("An error occurred when saving changes.", ex)
' Handle any errors that may occur during insert, such as a constraint violation.
Catch ex As DataServiceRequestException
Throw New ApplicationException("An error occurred when saving changes.", ex)

5.4.3. Cmo: Adjuntar una entidad existente a DataServiceContext


Cuando una entidad ya existe en un servicio de datos, la biblioteca de cliente de WCF Data Services le
permite adjuntar un objeto que representa directamente la entidad en la clase DataServiceContext sin
ejecutar una consulta primero.

Ejemplo
En el ejemplo siguiente se muestra cmo crear un objeto Customer existente que contiene cambios que se
van a guardar en el servicio de datos. Se adjunta el objeto al contexto y se llama al mtodo UpdateObject
para marcar el objeto adjunto como Modified antes de llamar al mtodo SaveChanges.
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define an existing customer to attach, including the key.
Dim customer As Customer = customer.CreateCustomer("ALFKI", "Alfreds Futterkiste")
' Set current property values.
customer.Address = "Obere Str. 57"
customer.City = "Berlin"
customer.PostalCode = "12209"
customer.Country = "Germany"
' Set property values to update.
customer.ContactName = "Peter Franken"
customer.ContactTitle = "Marketing Manager"
customer.Phone = "089-0877310"
customer.Fax = "089-0877451"
Try
' Attach the existing customer to the context and mark it as updated.
context.AttachTo("Customers", customer)
context.UpdateObject(customer)
' Send updates to the data service.
context.SaveChanges()
Catch ex As DataServiceClientException
Throw New ApplicationException("An error occurred when saving changes.", ex)
End Try

MCT: Luis Dueas

Pag 104 de 128

WCF Data Service

5.5. Operaciones asincrnicas


Las aplicaciones web deben tolerar una latencia superior entre cliente y servidor que las aplicaciones que se
ejecutan en redes internas. Para optimizar el rendimiento y la experiencia del usuario de la aplicacin, se
recomienda usar los mtodos asincrnicos de las clases DataServiceContext y DataServiceQuery cuando se
tenga acceso a los servidores de WCF Data Services en la web.
Aunque los servidores de WCF Data Services procesen solicitudes HTTP de forma sincrnica, algunos
mtodos de las bibliotecas de cliente de WCF Data Services son sincrnicas y esperan hasta que se
complete el intercambio completo de solicitudes y respuestas antes de continuar con la ejecucin. Los
mtodos asincrnicos de las bibliotecas de cliente de WCF Data Services no esperan a que se complete este
intercambio y pueden permitir que la aplicacin mantenga una interfaz de usuario que siga respondiendo
mientras tanto.
Puede realizar operaciones asincrnicas usando un par de mtodos de las clases DataServiceQuery y
DataServiceContext cuyos nombres comienzan por Begin y End, respectivamente. Los mtodos Begin
registran un delegado al que llama el servicio cuando finaliza la operacin. Se debera llamar a los mtodos
End en el delegado registrado para controlar la devolucin de llamada desde las operaciones completadas.
Cuando llame al mtodo End para completar una operacin asincrnica, debe hacer lo mismo desde la
misma instancia de DataServiceQuery o DataServiceContext que us para comenzar la operacin. Cada
mtodo Begin toma un parmetro state que puede pasar un objeto de estado a la devolucin de llamada.
Este objeto de estado se recupera desde la interfaz IAsyncResult que se proporciona con la devolucin de
llamada y se usa para llamar al mtodo End correspondiente para completar la operacin asincrnica. Por
ejemplo, cuando se proporciona la instancia de DataServiceQuery como parmetro state al llamar al
mtodo BeginExecute de la instancia, IAsyncResult devuelve la misma instancia de DataServiceQuery. A
continuacin, esta instancia de DataServiceQuery se usa para llamar al mtodo EndExecute para completar
la operacin de consulta.
Nota:
Las bibliotecas de cliente que se proporcionan en .NET Framework para Silverlight solo admiten operaciones
asincrnicas.
Las bibliotecas de cliente de .NET Framework admiten las siguientes operaciones asincrnicas:
Operacin

Mtodos
BeginExecute

Ejecutar una instancia de DataServiceQuery.

EndExecute
BeginExecute

Ejecutar una consulta desde la instancia de DataServiceContext.

EndExecute
BeginExecuteBatch

Ejecutar una consulta por lotes desde la instancia de DataServiceContext.

EndExecuteBatch
BeginLoadProperty

Cargar una entidad relacionada en la instancia de DataServiceContext.

Guardar los cambios efectuados en los objetos en la instancia de


DataServiceContext

EndLoadProperty
BeginSaveChanges
EndSaveChanges

Consideraciones sobre los subprocesos para las operaciones asincrnicas

MCT: Luis Dueas

Pag 105 de 128

WCF Data Service


En una aplicacin multiproceso, al delegado que se registra como devolucin de llamada para la operacin
asincrnica no se le invoca necesariamente en el mismo subproceso que se us para llamar al mtodo
Begin, encargado de crear la solicitud inicial. En una aplicacin cuya devolucin de llamada se debe invocar
en un subproceso concreto, debe calcular explcitamente las referencias a la ejecucin del mtodo End, que
controla la respuesta, para el subproceso deseado. Por ejemplo, en las aplicaciones basadas en Windows
Presentation Foundation (WPF) y en las aplicaciones basadas en Silverlight, se deben calcular las referencias
a la respuesta para el subproceso de interfaz de usuario mediante el mtodo BeginInvoke en el objeto
Dispatcher.

5.5.1. Cmo: Ejecutar consultas de servicio de datos asincrnicos


Al usar la biblioteca de cliente de WCF Data Services , puede realizar operaciones cliente-servidor, como
ejecutar consultas y guardar cambios, de forma asincrnica.
Nota:
En una aplicacin donde se debe invocar la devolucin de llamada en un subproceso concreto, debe
calcular explcitamente las referencias de la ejecucin del mtodo EndExecute.

Ejemplo
En el siguiente ejemplo se muestra cmo ejecutar una consulta asincrnica llamando al mtodo
BeginExecute para iniciar la consulta. El delegado alineado llama al mtodo EndExecute para mostrar los
resultados de la consulta.
Public Shared Sub BeginExecuteCustomersQuery()
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define the delegate to callback into the process
Dim callback As AsyncCallback = AddressOf OnCustomersQueryComplete
' Define the query to execute asynchronously that returns
' all customers with their respective orders.
Dim query As DataServiceQuery(Of Customer) = context.Customers.Expand("Orders")
Try
' Begin query execution, supplying a method to handle the response
' and the original query object to maintain state in the callback.
query.BeginExecute(callback, query)
Catch ex As DataServiceQueryException
Throw New ApplicationException("An error occurred during query execution.", ex)
End Try
End Sub
' Handle the query callback.
Private Shared Sub OnCustomersQueryComplete(ByVal result As IAsyncResult)
' Get the original query from the result.
Dim query As DataServiceQuery(Of Customer) = CType(result.AsyncState, DataServiceQuery(Of Customer))
' Complete the query execution.
For Each customer As Customer In query.EndExecute(result)
Console.WriteLine("Customer Name: {0}", customer.CompanyName)
For Each order As Order In customer.Orders
Console.WriteLine("Order #: {0} - Freight $: {1}", order.OrderID, order.Freight)
Next
Next
End Sub

5.5.2. Cmo: Crear una aplicacin asincrnica de WPF


MCT: Luis Dueas

Pag 106 de 128

WCF Data Service


Con WCF Data Services , puede enlazar los datos obtenidos de un servicio de datos a los elementos de la
interfaz de usuario de una aplicacin de Windows Presentation Framework (WPF). Tambin puede ejecutar
operaciones con el servicio de datos de una manera asincrnica, lo que permite a la aplicacin continuar
respondiendo mientras espera una respuesta a una solicitud al servicio de datos. Las aplicaciones para
Silverlight deben tener acceso al servicio de datos de forma asincrnica.
En este tema se muestra cmo tener acceso a un servicio de datos de forma asincrnica y enlazar los
resultados a los elementos de una aplicacin WPF. En los ejemplos de este tema se usa el servicio de datos
de ejemplo Northwind y las clases del servicio de datos del cliente generadas automticamente. Se crean
este servicio y las clases de datos del cliente al completar el tutorial rpido de WCF Data Services.

Ejemplo
El cdigo XAML siguiente define la ventana de la aplicacin WPF.
<Window x:Class="CustomerOrdersAsync"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="423" Width="679" Loaded="Window_Loaded" >
<Grid Name="LayoutRoot">
<StackPanel Orientation="Vertical" Height="Auto" Width="Auto">
<Label Content="Customer ID" Margin="20,0,0,0" />
<ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120"
HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
<ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}"
Header="Order ID" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}"
Header="Order Date" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}"
Header="Freight Cost" Width="50"/>
</GridView>
</ListView.View>
</ListView>
<Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click"
Width="80" Height="30" Margin="450,0,0,0"/>
</StackPanel>
</Grid>
</Window>

La pgina de cdigo subyacente siguiente para el archivo XAML ejecuta una consulta asincrnica usando el
servicio de datos y enlaza los resultados a los elementos de la ventana de WPF.
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media

MCT: Luis Dueas

Pag 107 de 128

WCF Data Service


Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports NorthwindClient.Northwind
Imports System.Data.Services.Client
Imports System.Windows.Threading
'/ <summary>
'/ Interaction logic for OrderItems.xaml
'/ </summary>
Partial Public Class CustomerOrdersAsync
Inherits Window
Dim context As NorthwindEntities
Private Shared customerBinding As DataServiceCollection(Of Customer)
Private Const customerCountry As String = "Germany"
' Change this URI to the service URI for your implementation.
Private Const svcUri As String = "http://localhost:12345/Northwind.svc/"
' Define a persisted result.
Private Shared currentResult As IAsyncResult
Delegate Sub DispatcherDelegate()
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Initialize the context.
context = New NorthwindEntities(New Uri(svcUri))
' Define the delegate to callback into the process
Dim callback As AsyncCallback = AddressOf OnQueryCompleted
' Define a query that returns customers and orders for a specific country.
Dim query As DataServiceQuery(Of Customer) = context.Customers.Expand("Orders") _
.AddQueryOption("filter", "Country eq '" + customerCountry + "'")
Try
' Begin asynchronously saving changes Imports the
' specified handler and query object state.
query.BeginExecute(callback, query)
Catch ex As DataServiceClientException
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub OnQueryCompleted(ByVal result As IAsyncResult)
' Persist the query result for the delegate.
currentResult = result
' Use the Dispatcher to ensure that the
' asynchronous call returns in the correct thread.
Dispatcher.BeginInvoke(New DispatcherDelegate(AddressOf QueryCompletedByDispatcher))
End Sub
' Handle the query callback.
Private Sub QueryCompletedByDispatcher()
Try
' Get the original query back from the result.
Dim query = CType(currentResult.AsyncState, DataServiceQuery(Of Customer))
' Instantiate the binding collection imports the
' results of the query execution.
customerBinding = New DataServiceCollection(Of Customer)(query.EndExecute(currentResult))
' Bind the collection to the root element of the UI.
Me.LayoutRoot.DataContext = customerBinding

MCT: Luis Dueas

Pag 108 de 128

WCF Data Service


Catch ex As DataServiceRequestException
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub saveChangesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Define the delegate to callback into the process
Dim callback As AsyncCallback = AddressOf OnSaveChangesCompleted
Try
' Start the asynchronous call to save changes.
context.BeginSaveChanges(callback, Nothing)
Catch ex As DataServiceClientException
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub OnSaveChangesCompleted(ByVal result As IAsyncResult)
' Persist the query result for the delegate.
currentResult = result
' Use the Dispatcher to ensure that the operation returns in the UI thread.
Me.Dispatcher.BeginInvoke(New DispatcherDelegate(AddressOf SaveChangesCompletedByDispatcher))
' Handle the query callback.
End Sub
Private Sub SaveChangesCompletedByDispatcher()
Try
' Complete the save changes operation.
context.EndSaveChanges(currentResult)
Catch ex As DataServiceRequestException
MessageBox.Show(ex.ToString())
End Try
End Sub
End Class

5.6. Realizar operaciones por lotes


Open Data Protocol (OData) admite procesamiento por lotes de solicitudes en un servicio basado en OData
. En WCF Data Services , cada operacin que use la clase DataServiceContext, como ejecutar una consulta o
guardar cambios, tiene como resultado el envo de una solicitud independiente al servicio de datos. Para
mantener un nmero razonable de conjuntos de operaciones, puede definir los lotes operacionales
explcitamente. Esto garantiza que todas las operaciones del lote se envan al servicio de datos en una nica
solicitud HTTP, permite al servidor procesar las operaciones automticamente y reduce el nmero de viajes
de ida y vuelta (round trip) al servicio de datos.

Operaciones de consulta por lotes


Para ejecutar varias consultas en un lote nico, debe crear cada consulta en el lote como una instancia
independiente de la clase DataServiceRequest. Al crear una solicitud de consulta de esta manera, la propia
consulta se define como un URI y sigue las reglas para el redireccionamiento de recursos. Las solicitudes de
consulta por lotes se envan al servicio de datos cuando se llama al mtodo ExecuteBatch, que contiene los
objetos de la solicitud de consulta. Este mtodo devuelve un objeto DataServiceResponse, que es una
coleccin de objetos QueryOperationResponse que representan las respuestas a las consultas individuales
del lote, cada una de los cuales contiene una coleccin de los objetos devueltos por la consulta o la
informacin del error. Cuando se produce un error en cualquier operacin de consulta nica en el lote, se
devuelve la informacin del error en el objeto QueryOperationResponse para la operacin fallida, pero se
siguen ejecutando las operaciones restantes.
Las consultas por lotes se pueden ejecutar tambin de forma asincrnica.

MCT: Luis Dueas

Pag 109 de 128

WCF Data Service

Procesamiento por lotes de la operacin SaveChanges


Al llamar al mtodo SaveChanges, todos los cambios detectados por el contexto se traducen en
operaciones basadas en REST, que se envan como solicitudes al servicio OData . De forma predeterminada,
estos cambios no se envan en un mensaje de solicitud nico. Para requerir que todos los cambios se enven
en una solicitud nica, debe llamar al mtodo SaveChanges e incluir un valor de Batch en la enumeracin
SaveChangesOptions que proporcione al mtodo.
Tambin puede guardar de forma asincrnica los cambios por lotes.

5.6.1. Cmo: Ejecutar consultas por lotes


La biblioteca de cliente de WCF Data Services le permite ejecutar ms de una consulta en el servicio de
datos de un solo lote.

Ejemplo
En el ejemplo siguiente se muestra cmo llamar al mtodo ExecuteBatch para ejecutar una matriz de los
objetos DataServiceRequest que contiene consultas que devuelven objetos Products y Customers del
servicio de datos de Northwind. La coleccin de objetos QueryOperationResponse del objeto
DataServiceResponse devuelto es de tipo enumerado y la coleccin de objetos contenida en cada
QueryOperationResponse tambin lo es.
Dim customerId = "ALFKI"
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Create the separate query URI's, one that returns
' a single customer and another that returns all Products.
Dim customerUri = New Uri(svcUri.AbsoluteUri & "/Customers('" & customerId & "')/?$expand=Orders")
Dim productsUri = New Uri(svcUri.AbsoluteUri & "/Products")
' Create the query requests.
Dim customerQuery = New DataServiceRequest(Of Customer)(customerUri)
Dim productsQuery = New DataServiceRequest(Of Product)(productsUri)
' Add the query requests to a batch request array.
Dim batchRequests = New DataServiceRequest() {customerQuery, productsQuery}
Dim batchResponse As DataServiceResponse
Try
' Execute the query batch and get the response.
batchResponse = context.ExecuteBatch(batchRequests)
If batchResponse.IsBatchResponse Then
' Parse the batchResponse.BatchHeaders.
End If
' Enumerate over the results of the query.
For Each response As QueryOperationResponse In batchResponse
' Handle an error response.
If response.StatusCode > 299 OrElse response.StatusCode < 200 Then
Console.WriteLine("An error occurred.")
Console.WriteLine(response.Error.Message)
Else
' Find the response for the Customers query.
If response.Query.ElementType Is GetType(Customer) Then
For Each customer As Customer In response
Console.WriteLine("Customer: {0}", customer.CompanyName)
For Each order As Order In customer.Orders
Console.WriteLine("Order ID: {0} - Freight: {1}", order.OrderID, order.Freight)
Next

MCT: Luis Dueas

Pag 110 de 128

WCF Data Service


Next
' Find the response for the Products query.
ElseIf response.Query.ElementType Is GetType(Product) Then
For Each product As Product In response
Console.WriteLine("Product: {0}", product.ProductName)
Next
End If
End If
Next
' This type of error is raised when the data service returns with
' a response code < 200 or >299 in the top level element.
Catch ex As DataServiceRequestException
' Get the response from the exception.
batchResponse = ex.Response
If (batchResponse.IsBatchResponse) Then
' Parse the batchResponse.BatchHeaders.
End If
For Each response As QueryOperationResponse In batchResponse
If response.Error IsNot Nothing Then
Console.WriteLine("An error occurred.")
Console.WriteLine(response.Error.Message)
End If
Next
End Try

5.7. Enlazar datos a controles


Con WCF Data Services , puede enlazar controles como ComboBox y ListView a una instancia de la clase
DataServiceCollection. Esta coleccin, que hereda de la clase ObservableCollection, contiene los datos de
una fuente Open Data Protocol (OData) . Esta clase representa una coleccin de datos dinmicos que
proporciona notificaciones si se agregan o se quitan elementos. Al usar una instancia de
DataServiceCollection para el enlace de datos, las bibliotecas de cliente de WCF Data Services administran
estos eventos para garantizar que los objetos supervisados por DataServiceContext sigan estando
sincronizados con los datos en el elemento de la interfaz de usuario enlazada.
La clase DataServiceCollection(indirectamente) implementa la interfaz INotifyCollectionChanged para
avisar al contexto en el momento en el que se agreguen o quiten objetos de la coleccin. Los objetos de
tipo de servicio de datos usados con una clase DataServiceCollection tambin deben implementar la
interfaz INotifyPropertyChanged para avisar a la clase DataServiceCollection en el momento en el que
cambien las propiedades de los objetos en la coleccin de enlaces.
Nota:
Al utilizar el cuadro de dilogo Agregar referencia de servicio o la herramienta DataSvcUtil.exe con la
opcin /dataservicecollection para generar las clases de servicio de datos de cliente, las clases de datos
generadas implementan la interfaz INotifyPropertyChanged.

Crear la coleccin de enlaces


Cree una nueva instancia de la clase DataServiceCollection llamando a uno de los mtodos de constructor
de clase con una instancia DataServiceContext proporcionada y, opcionalmente, una consulta
DataServiceQuery o LINQ que, cuando se ejecuta, devuelve una instancia IEnumerable. IEnumerable
proporciona el origen de objetos para la coleccin de enlaces, que se materializan de una fuente OData . De
manera predeterminada, DataServiceContext realiza automticamente el seguimiento de los cambios
realizados en los objetos enlazados y elementos insertados en la coleccin. Si necesita realizar el

MCT: Luis Dueas

Pag 111 de 128

WCF Data Service


seguimiento de estos cambios manualmente, llame a uno de los mtodos de constructor que toma un
parmetro trackingMode y especifica un valor del campo None.
En el siguiente ejemplo se muestra cmo crear una instancia de la clase DataServiceCollection basada en
un DataServiceContext proporcionado y una DataServiceQuery que devuelve todos los clientes con
pedidos (en el ejemplo, Orders) relacionados:
' Create a new collection that contains all customers and related orders.
Dim trackedCustomers As DataServiceCollection(Of Customer) = _
New DataServiceCollection(Of Customer)(context.Customers.Expand("Orders"))

Enlazar datos a elementos de Windows Presentation Foundation


Dado que la clase DataServiceCollection se hereda de la clase ObservableCollection, puede enlazar los
objetos a un elemento o control en una aplicacin Windows Presentation Foundation (WPF) tal como lo
hara si usara la clase ObservableCollection para el enlace. Una manera de enlazar los datos del servicio de
datos a controles WPF es establecer la propiedad DataContext del elemento para la instancia de la clase
DataServiceCollection que contiene el resultado de la consulta. En este caso, usted utiliza la propiedad
ItemsSource para establecer el origen del objeto para el control. Utilice la propiedad DisplayMemberPath
para especificar qu propiedad mostrar del objeto enlazado. Si est enlazando un elemento a un objeto
relacionado que devuelve una propiedad de navegacin, incluya la ruta de acceso en el enlace definido para
la propiedad ItemsSource. Esta ruta de acceso es relativa al objeto raz establecido por la propiedad
DataContext del control primario. En el siguiente ejemplo se establece la propiedad DataContext de un
elemento StackPanel para enlazar el control primario a una clase DataServiceCollection de objetos de
cliente:
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery,
TrackingMode.AutoChangeTracking, "Customers", _
AddressOf OnMyPropertyChanged, AddressOf OnMyCollectionChanged)
' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers

En el ejemplo siguiente se muestra la definicin de enlace XAML de los controles secundarios DataGrid y
ComboBox:
<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
<Label Content="Customer ID" Margin="20,0,0,0" />
<ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120"
HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
<ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}"
Header="Order ID" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}"
Header="Order Date" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}"
Header="Freight Cost" Width="50"/>
</GridView>
</ListView.View>
</ListView>
<Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click"
Width="80" Height="30" Margin="450,0,0,0"/>

MCT: Luis Dueas

Pag 112 de 128

WCF Data Service


</StackPanel>

Cuando una entidad participa en una relacin de uno a varios o de varios a varios, la propiedad de
navegacin para la relacin devuelve una coleccin de objetos relacionados. Cuando usted utiliza el cuadro
de dilogo Agregar referencia de servicio o la herramienta DataSvcUtil.exe para generar las clases de
servicio de datos de cliente, la propiedad de navegacin devuelve una instancia de la clase
DataServiceCollection. Esto le permite enlazar objetos relacionados a un control, as como admitir
escenarios de enlace de WPF comunes, como el patrn de enlace principal-detalle para entidades
relacionadas. En el ejemplo XAML anterior, el cdigo XAML enlaza la clase principal DataServiceCollection
al elemento de datos de raz. El pedido DataGrid se enlaza a la clase DataServiceCollection de pedidos
devueltos desde el objeto Customers seleccionado, que se enlaza a su vez al elemento de datos de raz de
Window.

Enlazar datos a controles de Windows Forms


Para enlazar objetos a un control de Windows Form, establezca la propiedad DataSource del control en la
instancia de la clase DataServiceCollection que contiene el resultado de la consulta.
Nota:
El enlace de datos solo se admite para los controles que realizan escuchas de los eventos de cambio
mediante la implementacin de las interfaces INotifyPropertyChanged y INotifyCollectionChanged.
Cuando un control no admite este tipo de notificacin de cambios, los cambios que se realizan en la clase
DataServiceCollection subyacente no se reflejan en el control enlazado.
En el siguiente ejemplo DataServiceCollection se enlaza a ComboBox:
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
'Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID"
customersComboBox.DataSource = trackedCustomers

Cuando utiliza el cuadro de dilogo Agregar referencia de servicio para generar las clases de servicio de
datos de cliente, tambin se crea un origen de datos de proyecto basado en el DataServiceContext
generado. Con este origen de datos, puede crear controles o elementos de la interfaz de usuario que
muestren datos del servicio de datos simplemente arrastrando los elementos desde la ventana Orgenes de
datos hasta el diseador. Estos elementos aparecen en la interfaz de usuario de la aplicacin y se enlazan al
origen de datos.

Enlazar datos paginados


Un servicio de datos se puede configurar para limitar la cantidad de datos consultados que se devuelven en
un nico mensaje de respuesta. Cuando el servicio de datos est paginando los datos de respuesta, cada
respuesta contiene un vnculo que se utiliza para devolver la pgina siguiente de resultados. En este caso,
debe cargar las pginas explcitamente llamando al mtodo Load en la clase DataServiceCollection,
especificando el URI obtenido de la propiedad NextLinkUri, como en el siguiente ejemplo:
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
' Load all pages of the response at once.
While trackedCustomers.Continuation IsNot Nothing
trackedCustomers.Load(context.Execute(Of Customer)(trackedCustomers.Continuation.NextLinkUri))
End While

Los objetos relacionados se cargan de una manera similar.

Personalizar comportamientos de enlace de datos


La clase DataServiceCollection le permite interceptar los eventos que se provocan al realizar cambios en la
coleccin (como agregar o quitar un objeto) o en las propiedades de objeto en una coleccin. Puede
modificar los eventos de enlace de datos para reemplazar el comportamiento predeterminado, que incluye
las siguientes restricciones:

MCT: Luis Dueas

Pag 113 de 128

WCF Data Service


No se realiza ninguna validacin dentro de los delegados.
Al agregar una entidad, se agregan automticamente las entidades relacionadas.
Al eliminar una entidad, no se eliminan las entidades relacionadas.
Al crear una nueva instancia de DataServiceCollection, tiene la opcin de especificar los siguientes
parmetros, que definen los delegados para los mtodos que administran los eventos provocados cuando
se cambian los objetos enlazados:
entityChanged: mtodo al que se llama cuando cambia la propiedad de un objeto enlazado. Este
delegado Func acepta un objeto EntityChangedParams y devuelve un valor booleano que indica si
el comportamiento predeterminado, que consiste en llamar a UpdateObject en
DataServiceContext, todava se debera producir.
entityCollectionChanged: mtodo al que se llama cuando un objeto se agrega o se quita de la
coleccin de enlaces. Este delegado Func acepta un objeto EntityCollectionChangedParams y
devuelve un valor booleano que indica si el comportamiento predeterminado, que consiste en
llamar a AddObject para una accin Add o a DeleteObject para una accin Remove en
DataServiceContext, an se debe producir.
Nota:
WCF Data Services no realiza ninguna validacin de los comportamientos personalizados que implementa el
usuario en estos delegados.
En el siguiente ejemplo, la accin Remove est personalizada para llamar al mtodo DeleteObject y
DeleteLink con el fin de quitar las entidades Orders_Details que pertenecen a una entidad Orders
eliminada. Esta accin personalizada se realiza porque las entidades dependientes no se eliminan
automticamente cuando se elimina la entidad primaria.
' Method that is called when the CollectionChanged event is handled.
Private Function OnMyCollectionChanged( _
ByVal entityCollectionChangedinfo As EntityCollectionChangedParams) As Boolean
If entityCollectionChangedinfo.Action = _
NotifyCollectionChangedAction.Remove Then
' Delete the related items when an order is deleted.
If entityCollectionChangedinfo.TargetEntity.GetType() Is GetType(Order) Then
' Get the context and object from the supplied parameter.
Dim context = entityCollectionChangedinfo.Context
Dim deletedOrder As Order = _
CType(entityCollectionChangedinfo.TargetEntity, Order)
If deletedOrder.Order_Details.Count = 0 Then
' Load the related OrderDetails.
context.LoadProperty(deletedOrder, "Order_Details")
End If
' Delete the order and its related items
For Each item As Order_Detail In deletedOrder.Order_Details
context.DeleteObject(item)
Next
' Delete the order and then return false since the object is already deleted.
context.DeleteObject(deletedOrder)
Return True
Else
Return False
End If
Else
' Use the default behavior.
Return False
End If

MCT: Luis Dueas

Pag 114 de 128

WCF Data Service


End Function

El comportamiento predeterminado cuando un objeto se quita de una clase DataServiceCollection


utilizando el mtodo Remove es que el objeto tambin se marca como eliminado en DataServiceContext.
Para cambiar este comportamiento puede especificar un delegado para un mtodo en el parmetro
entityCollectionChanged al que se llama cuando se produce el evento CollectionChanged.

Enlazar datos con clases de datos de cliente personalizadas


Para poder cargar los objetos en la clase DataServiceCollection, los objetos deben implementar la interfaz
INotifyPropertyChanged. Las clases de cliente del servicio de datos que se generan al utilizar el cuadro de
dilogo Agregar referencia de servicio o la herramienta DataSvcUtil.exe implementan esta interfaz. Si
proporciona sus propias clases de datos de cliente, debe utilizar otro tipo de coleccin para el enlace de
datos. Cuando los objetos cambian, debe administrar los eventos en los controles enlazados a datos para
que llamen a los siguientes mtodos de la clase DataServiceContext:
AddObject: cuando se agrega un nuevo objeto a la coleccin.
DeleteObject: cuando se elimina un objeto de la coleccin.
UpdateObject: cuando se cambia una propiedad en un objeto de la coleccin.
AddLink: cuando se agrega un objeto a una coleccin del objeto relacionado.
SetLink: cuando se agrega un objeto a una coleccin de objetos relacionados.

5.7.1. Cmo: Enlazar datos a los elementos de WPF


Con WCF Data Services , puede enlazar elementos de Windows Presentation Foundation (WPF) como la
clase ListBoxo la clase ComboBox a una instancia de la clase DataServiceCollection, que controla los eventos
generados por los controles para mantener la clase DataServiceContext sincronizada con los cambios
efectuados en los datos de los controles.

Ejemplo
El ejemplo siguiente corresponde a la pgina de cdigo subyacente de una pgina de lenguaje XAML que
define la ventana SalesOrders en WPF. Cuando se carga la ventana, se crea una DataServiceCollection
dependiendo del resultado de una consulta que devuelve los clientes filtrados por pas. Se cargan todas las
pginas de este resultado paginado, junto con los pedidos relacionados, y se enlazan a la propiedad
DataContext de StackPanel que es el control de diseo raz para la ventana de WPF.
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Data.Services.Client
Imports NorthwindClient.Northwind
Partial Public Class CustomerOrdersWpf3
Inherits Window
Private context As NorthwindEntities
Private trackedCustomers As DataServiceCollection(Of Customer)

MCT: Luis Dueas

Pag 115 de 128

WCF Data Service


Private Const customerCountry As String = "Germany"
Private Const svcUri As String = "http://localhost:12345/Northwind.svc/"
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Initialize the context for the data service.
context = New NorthwindEntities(New Uri(svcUri))
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
' Load all pages of the response at once.
While trackedCustomers.Continuation IsNot Nothing
trackedCustomers.Load(context.Execute(Of Customer)(trackedCustomers.Continuation.NextLinkUri))
End While
' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers
Catch ex As DataServiceQueryException
MessageBox.Show("The query could not be completed:\n" + ex.ToString())
Catch ex As InvalidOperationException
MessageBox.Show("The following error occurred:\n" + ex.ToString())
End Try
End Sub
Private Sub customerIDComboBox_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
Dim selectedCustomer As Customer = CType(Me.customerIDComboBox.SelectedItem, Customer)
Try
If selectedCustomer.Orders.Count = 0 Then
' Load the first page of related orders for the selected customer.
context.LoadProperty(selectedCustomer, "Orders")
End If
' Load all remaining pages.
While selectedCustomer.Orders.Continuation IsNot Nothing
selectedCustomer.Orders.Load(context.Execute(Of Order)(selectedCustomer.Orders.Continuation.NextLinkUri))
End While
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub saveChangesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Save changes to the data service.
context.SaveChanges()
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
End Class

El siguiente XAML define la ventana SalesOrders en WPF del ejemplo anterior.


<Window x:Class="CustomerOrdersWpf3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

MCT: Luis Dueas

Pag 116 de 128

WCF Data Service


xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="423" Width="679" Loaded="Window_Loaded">
<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
<Label Content="Customer ID" Margin="20,0,0,0" />
<ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}"
SelectionChanged="customerIDComboBox_SelectionChanged"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120"
HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
<ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}"
Header="Order ID" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}"
Header="Order Date" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}"
Header="Freight Cost" Width="50"/>
</GridView>
</ListView.View>
</ListView>
<Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click"
Width="80" Height="30" Margin="450,0,0,0"/>
</StackPanel>
</Window>

El ejemplo siguiente corresponde a la pgina de cdigo subyacente de una pgina de lenguaje XAML que
define la ventana SalesOrders en WPF. Cuando se carga la ventana, se crea una DataServiceCollection
dependiendo del resultado de una consulta que devuelve los clientes con objetos relacionados, filtrados por
pas. Este resultado se enlaza a la propiedad DataContext de StackPanel que es el control de diseo raz
para la ventana de WPF.
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Data.Services.Client
Imports NorthwindClient.Northwind
Partial Public Class CustomerOrdersWpf
Inherits Window
Private context As NorthwindEntities
Private trackedCustomers As DataServiceCollection(Of Customer)
Private Const customerCountry As String = "Germany"
Private Const svcUri As String = "http://localhost:12345/Northwind.svc/"
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

MCT: Luis Dueas

Pag 117 de 128

WCF Data Service


Try
' Initialize the context for the data service.
context = New NorthwindEntities(New Uri(svcUri))
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers
Catch ex As DataServiceQueryException
MessageBox.Show("The query could not be completed:\n" + ex.ToString())
Catch ex As InvalidOperationException
MessageBox.Show("The following error occurred:\n" + ex.ToString())
End Try
End Sub
Private Sub saveChangesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Save changes to the data service.
context.SaveChanges()
End Sub
End Class

El siguiente XAML define la ventana SalesOrders en WPF del ejemplo anterior.


<Window x:Class="CustomerOrdersWpf"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="423" Width="679" Loaded="Window_Loaded">
<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
<Label Content="Customer ID" Margin="20,0,0,0" />
<ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120"
HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
<ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}"
Header="Order ID" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}"
Header="Order Date" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}"
Header="Freight Cost" Width="50"/>
</GridView>
</ListView.View>
</ListView>
<Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click"
Width="80" Height="30" Margin="450,0,0,0"/>
</StackPanel>
</Window>

MCT: Luis Dueas

Pag 118 de 128

WCF Data Service

5.7.2. Cmo: Enlazar datos mediante un origen de datos del


proyecto
Puede crear orgenes de datos basados en los objetos de datos generados en una aplicacin cliente de WCF
Data Services . Cuando se agrega una referencia a un servicio de datos usando el cuadro de dilogo
Agregar referencia de servicio, se crea un origen de datos del proyecto junto con las clases generadas de
datos del cliente. Para cada conjunto de entidades expuesto por el servicio de datos se crea un origen de
datos. Puede crear formularios que muestran datos procedentes del servicio arrastrando estos elementos
del origen de datos desde la ventana Orgenes de datos al diseador. Estos elementos se convierten en
controles enlazados al origen de datos. Durante la ejecucin, este origen de datos se enlaza a una instancia
de la clase DataServiceCollection, que se rellena con los objetos devueltos por una consulta al servicio de
datos.

Para usar un origen de datos del proyecto en una ventana de WPF


1.

En un proyecto WPF, agregue una referencia al servicio de datos de Northwind.

2.

En la ventana Orgenes de datos, expanda el nodo Customers del origen de datos del proyecto

3.

NorthwindEntities.
Haga clic en el elemento CustomerID, seleccione ComboBox en la lista y arrastre el elemento
CustomerID desde el nodo Customers al diseador.
Con ello se crean los siguientes elementos de objeto en el archivo XAML de la ventana:

Un elemento CollectionViewSource denominado customersViewSource. La propiedad


DataContext del elemento de objeto Grid de nivel superior se establece en este nuevo
elemento CollectionViewSource.

4.

Un control ComboBox enlazado a datos denominado CustomerID.

Un control Label.

Arrastre la propiedad de navegacin Orders al diseador.


Con ello se crean los siguientes elementos de objeto adicionales en el archivo XAML de la ventana:

Un

segundo

elemento

CollectionViewSource

denominado

customersOrdersViewSource, cuyo origen es customerViewSource.


o

Un control DataGrid enlazado a datos denominado ordersDataGrid.

5.
6.

(Opcional) Arrastre elementos adicionales desde el nodo Customers al diseador.


Abra la pgina de cdigo del formulario y agregue las instrucciones using siguientes (Imports en
Visual Basic):

7.

En la clase parcial que define el formulario, agregue el cdigo siguiente que crea una instancia de
ObjectContext y define la constante customerID.
Private context As NorthwindEntities
Private customersViewSource As CollectionViewSource
Private trackedCustomers As DataServiceCollection(Of Customer)
Private Const customerCountry As String = "Germany"
Private Const svcUri As String = "http://localhost:12345/Northwind.svc/"

8.

En el diseador, seleccione la ventana.


Nota:
Asegrese de que selecciona la ventana, y no el contenido situado dentro de ella. Cuando est
seleccionada la ventana, el cuadro de texto Nombre situado cerca de la parte superior de la

MCT: Luis Dueas

Pag 119 de 128

WCF Data Service


ventana Propiedades debera contener el nombre de la ventana.
9. En la ventana Propiedades, seleccione el botn Eventos.
10. Busque el evento Loaded y, a continuacin, haga doble clic en la lista desplegable situada junto a
este evento.
Visual Studio abre el archivo de cdigo subyacente para la ventana y genera un controlador de
eventos Loaded.
11. En el controlador de eventos Loaded que se acaba de crear, copie y pegue el cdigo siguiente.
' Initialize the context for the data service.
context = New NorthwindEntities(New Uri(svcUri))
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
try
' Get the customersViewSource resource and set the binding to the collection.
customersViewSource = CType(Me.FindResource("customersViewSource"), CollectionViewSource)
customersViewSource.Source = trackedCustomers
customersViewSource.View.MoveCurrentToFirst()
Catch ex As DataServiceQueryException
MessageBox.Show("The query could not be completed:\n" + ex.ToString())
Catch ex As InvalidOperationException
MessageBox.Show("The following error occurred:\n" + ex.ToString())
End Try

12. Este cdigo crea una instancia de DataServiceCollection para el tipo Customers basndose en la
ejecucin de una consulta LINQ que devuelve una interfaz IEnumerable de Customers junto con
los objetos Orders relacionados desde el servicio de datos de Northwind y la enlaza con el
elemento customersViewSource.

Para usar un origen de datos del proyecto en un formulario de Windows


1.

En la ventana Orgenes de datos, expanda el nodo Customers del origen de datos del proyecto
NorthwindEntities.

2.

Haga clic en el elemento CustomerID, seleccione ComboBox en la lista y arrastre el elemento


CustomerID desde el nodo Customers al diseador.
De esta forma se crean los controles siguientes en el formulario:

Una instancia de BindingSource denominada customersBindingSource.

Una instancia de BindingNavigator denominada customersBindingNavigator. Puede


eliminar este control, dado que no ser necesario.

Un control ComboBox enlazado a datos denominado CustomerID.

Un control Label.

3.

Arrastre la propiedad de navegacin Orders al formulario.

4.

De esta forma se crea el control ordersBindingSource con la propiedad DataSource del control
establecida en customersBindingSource y la propiedad DataMember establecida en Customers.

MCT: Luis Dueas

Pag 120 de 128

WCF Data Service


Tambin se crea el control enlazado a datos ordersDataGridView en el formulario, acompaado
5.
6.

de un control de etiqueta con el ttulo apropiado.


(Opcional) Arrastre elementos adicionales desde el nodo Customers al diseador.
Abra la pgina de cdigo del formulario y agregue las instrucciones using siguientes (Imports en
Visual Basic):
Imports System.Data.Services.Client
Imports NorthwindClient.Northwind

7.

En la clase parcial que define el formulario, agregue el cdigo siguiente que crea una instancia de
ObjectContext y define la constante customerID.
Private context As NorthwindEntities
Private trackedCustomers As DataServiceCollection(Of Customer)
Private Const customerCountry As String = "Germany"
Private Const svcUri As String = "http:'localhost:12345/Northwind.svc/"

8.

En el diseador de formularios, haga doble clic en el formulario.


De esta forma se abre la pgina de cdigo del formulario y se crea el mtodo que administra el
evento Load para el formulario.

9.

En el controlador de eventos Load, copie y pegue el cdigo siguiente.


' Initialize the context for the data service.
context = New NorthwindEntities(New Uri(svcUri))
Try
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)
'Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID"
customersComboBox.DataSource = trackedCustomers
Catch ex As DataServiceQueryException
MessageBox.Show("The query could not be completed:\n" + ex.ToString())
Catch ex As InvalidOperationException
MessageBox.Show("The following error occurred:\n" + ex.ToString())

10. Este cdigo crea una instancia de DataServiceCollection para el tipo Customers basndose en la
ejecucin de una instancia de DataServiceQuery que devuelve una interfaz IEnumerable de

Customers desde el servicio de datos de Northwind y la enlaza con el elemento


customersBindingSource.

5.7.3. Cmo: Personalizar comportamientos de enlace de datos


Con WCF Data Services , puede proporcionar lgica personalizada a la que DataServiceCollection llama
cuando se agrega o se quita un objeto de la coleccin de enlaces o cuando se detecta un cambio en una
propiedad. Esta lgica personalizada se proporciona en forma de mtodos, a los que se hace referencia
como delegados Func, que devuelven un valor false cuando an se debe ejecutar el comportamiento
predeterminado al completarse el mtodo personalizado y el valor true cuando se debe detener el
procesamiento posterior del evento.
Los ejemplos de este tema proporcionan mtodos personalizados para los parmetros
entityCollectionChanged y entityChanged de la clase DataServiceCollection. En los ejemplos de este tema

MCT: Luis Dueas

Pag 121 de 128

WCF Data Service


se usa el servicio de datos de ejemplo Northwind y las clases del servicio de datos del cliente generadas
automticamente. Se crean este servicio y las clases de datos del cliente al completar el tutorial rpido de
WCF Data Services.

Ejemplo
La siguiente pgina de cdigo subyacente para el archivo XAML crea una instancia de
DataServiceCollection con mtodos personalizados a los que se llama cuando se producen cambios en los
datos enlazados a la coleccin de enlaces. Cuando se produce el evento CollectionChanged, el mtodo
proporcionado evita que se elimine del servicio de datos un elemento que se ha quitado de la coleccin de
enlaces. Cuando se produce el evento PropertyChanged, se valida el valor de ShipDate para asegurarse de
que no se realizan cambios en los pedidos que ya han enviado.
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Data.Services.Client
Imports NorthwindClient.Northwind
Imports System.Collections.Specialized
Partial Public Class CustomerOrdersCustom
Inherits Window
Private context As NorthwindEntities
Private trackedCustomers As DataServiceCollection(Of Customer)
Private Const customerCountry As String = "Germany"
Private Const svcUri As String = "http://localhost:12345/Northwind.svc/"
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Initialize the context for the data service.
context = New NorthwindEntities(New Uri(svcUri))
' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
Where cust.Country = customerCountry Select cust
' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery, _
TrackingMode.AutoChangeTracking, "Customers", _
AddressOf OnMyPropertyChanged, AddressOf OnMyCollectionChanged)
' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers
Catch ex As DataServiceQueryException
MessageBox.Show("The query could not be completed:\n" + ex.ToString())
Catch ex As InvalidOperationException
MessageBox.Show("The following error occurred:\n" + ex.ToString())
End Try

MCT: Luis Dueas

Pag 122 de 128

WCF Data Service


End Sub
' Method that is called when the CollectionChanged event is handled.
Private Function OnMyCollectionChanged( _
ByVal entityCollectionChangedinfo As EntityCollectionChangedParams) As Boolean
If entityCollectionChangedinfo.Action = _
NotifyCollectionChangedAction.Remove Then
' Delete the related items when an order is deleted.
If entityCollectionChangedinfo.TargetEntity.GetType() Is GetType(Order) Then
' Get the context and object from the supplied parameter.
Dim context = entityCollectionChangedinfo.Context
Dim deletedOrder As Order = CType(entityCollectionChangedinfo.TargetEntity, Order)
If deletedOrder.Order_Details.Count = 0 Then
' Load the related OrderDetails.
context.LoadProperty(deletedOrder, "Order_Details")
End If
' Delete the order and its related items
For Each item As Order_Detail In deletedOrder.Order_Details
context.DeleteObject(item)
Next
' Delete the order and then return false since the object is already deleted.
context.DeleteObject(deletedOrder)
Return True
Else
Return False
End If
Else
' Use the default behavior.
Return False
End If
End Function
' Method that is called when the PropertyChanged event is handled.
Private Function OnMyPropertyChanged( _
ByVal entityChangedInfo As EntityChangedParams) As Boolean
' Validate a changed order to ensure that changes are not made
' after the order ships.
If entityChangedInfo.Entity.GetType() Is GetType(Order) AndAlso _
(CType(entityChangedInfo.Entity, Order).ShippedDate < DateTime.Today) Then
Throw New ApplicationException(String.Format( _
"The order {0} cannot be changed because it shipped on {1}.", _
CType(entityChangedInfo.Entity, Order).OrderID, _
CType(entityChangedInfo.Entity, Order).ShippedDate))
Return False
Else
Return True
End If
End Function
Private Sub deleteButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Get the Orders binding collection.
If customerIDComboBox.SelectedItem IsNot Nothing Then
Dim trackedOrders As DataServiceCollection(Of Order) = _
(CType(customerIDComboBox.SelectedItem, Customer)).Orders
' Remove the currently selected order.

MCT: Luis Dueas

Pag 123 de 128

WCF Data Service


trackedOrders.Remove(CType(ordersDataGrid.SelectedItem, Order))
End If
End Sub
Private Sub saveChangesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
' Save changes to the data service.
context.SaveChanges()
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
End Class

El cdigo XAML siguiente define la ventana del ejemplo anterior.


<Window x:Class="CustomerOrdersCustom"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="423" Width="679" Loaded="Window_Loaded" >
<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
<Label Content="Customer ID" Margin="20,0,0,0" />
<ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120"
HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
<ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}"
Header="Order ID" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}"
Header="Order Date" Width="50"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}"
Header="Freight Cost" Width="50"/>
</GridView>
</ListView.View>
</ListView>
<StackPanel Orientation="Horizontal">
<Button Name="deleteButton" Content="Delete Order" Click="deleteButton_Click"
Width="80" Height="30" Margin="450,0,10,0"/>
<Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click"
Width="80" Height="30" Margin="10,0,0,0"/>
</StackPanel>
</StackPanel>
</Window>

5.8. Administrar el contexto del servicio de datos


Nota:
En este tema se describe la nueva funcionalidad en WCF Data Services. Esta nueva funcionalidad admite la
versin 3 de Open Data Protocol (OData) y est disponible como actualizacin en la versin 4 de .NET
Framework. Puede descargar e instalar la actualizacin desde el Centro de Descarga de Microsoft.

MCT: Luis Dueas

Pag 124 de 128

WCF Data Service


La clase DataServiceContext encapsula las operaciones admitidas en un servicio de datos determinado. Los
servicios de OData carecen de estado, pero no ocurre lo mismo con el contexto. Por consiguiente, puede
usar la clase DataServiceContext para mantener el estado en el cliente entre las interacciones con el
servicio de datos para admitir caractersticas como la administracin de cambios. Esta clase tambin
administra las identidades y realiza el seguimiento de los cambios.

Opciones de combinacin y resolucin de identidad


Cuando se ejecuta el objeto DataServiceQuery, las entidades de la fuente de respuesta se materializan en
objetos. La forma en que las entradas de un mensaje de respuesta se materializan en objetos se basa en la
resolucin de identidades y depende de la opcin de combinacin con la que se ejecut la consulta.
Cuando varias consultas o solicitudes de carga se ejecutan en el mbito de un DataServiceContextnico, el
cliente WCF Data Services solo realiza el seguimiento de una nica instancia de objeto que tiene un valor de
clave concreto. Esta clave, que se utiliza para realizar la resolucin de identidades, identifica una entidad de
forma inequvoca.
De forma predeterminada, el cliente solo materializa una entrada de la fuente de respuesta en un objeto
para las entidades de las que an no realiza un seguimiento DataServiceContext. Esto significa que los
cambios en los objetos que ya estn en la memoria cach no se sobrescriben. Este comportamiento se
controla especificando un valor de MergeOption para las consultas y las operaciones de carga. Esta opcin
se especifica estableciendo la propiedad MergeOption en DataServiceContext. AppendOnly es el valor de
la opcin de combinacin predeterminada. De este modo, solo se materializan los objetos de entidades de
las que no se realiza un seguimiento, lo que significa que los objetos existentes no se sobrescriben. Otra
manera de evitar que los cambios en los objetos del cliente se sobrescriban con las actualizaciones del
servicio de datos es especificar PreserveChanges. Cuando se especifica OverwriteChanges, los valores de los
objetos del cliente son reemplazados por los valores ms recientes de las entradas de la fuente de
respuesta, aunque se hayan realizado cambios en estos objetos. Cuando se utiliza una opcin de
combinacin NoTracking, DataServiceContext no puede enviar los cambios realizados en los objetos de
cliente al servicio de datos. Con esta opcin, los cambios siempre se sobrescriben con valores del servicio de
datos.

Administrar la simultaneidad
OData admite la simultaneidad optimista que permite al servicio de datos detectar conflictos de
actualizacin. El proveedor del servicio de datos se puede configurar de manera que el servicio de datos
compruebe los cambios en las entidades mediante un token de simultaneidad. Este token incluye una o ms
propiedades de un tipo de entidad que el servicio de datos valida para determinar si un recurso ha
cambiado. El cliente de WCF Data Services administra los tokens de simultaneidad, que se incluyen en el
encabezado eTag de las solicitudes al servicio de datos y las respuestas de este.
DataServiceContext realiza el seguimiento de los cambios realizados en los objetos notificados
manualmente utilizando AddObject, UpdateObject y DeleteObject o mediante DataServiceCollection.
Cuando se llama al mtodo SaveChanges, el cliente devuelve los cambios al servicio de datos. SaveChanges
puede generar un error cuando los cambios de los datos en el cliente estn en conflicto con los cambios en
el servicio de datos. Cuando esto sucede, debe consultar de nuevo el recurso de entidad para recibir los
datos actualizados. Para sobrescribir los cambios en el servicio de datos, ejecute la consulta con la opcin
de combinacin PreserveChanges. Al llamar de nuevo al mtodo SaveChanges, los cambios conservados
en el cliente se mantienen en el servicio de datos, siempre que no se hayan realizado otros cambios en el
recurso del servicio de datos.

Guardar los cambios


El seguimiento de los cambios se realiza en la instancia de la clase DataServiceContext, pero los cambios
no se envan al servidor inmediatamente. Una vez que haya efectuado los cambios necesarios de una
actividad determinada, llame al mtodo SaveChanges para enviar todos los cambios al servicio de datos. Se
devuelve un objeto DataServiceResponse cuando finaliza la operacin SaveChanges. El objeto
DataServiceResponse incluye una secuencia de objetos OperationResponse que, a su vez, contienen una
secuencia de instancias de EntityDescriptor o LinkDescriptor que representan los cambios que se guardaron
o se intentaron realizar. Cuando se crea o modifica una entidad en el servicio de datos, la instancia de la
clase EntityDescriptor contiene una referencia a la entidad actualizada, que incluye los valores de
propiedad generados por el servidor, como el valor de ProductID generado en el ejemplo anterior. La

MCT: Luis Dueas

Pag 125 de 128

WCF Data Service


biblioteca cliente actualiza automticamente el objeto de .NET Framework para que tenga estos nuevos
valores.
En el caso de las operaciones de insercin y actualizacin correctas, la propiedad de estado del objeto
EntityDescriptor o del objeto LinkDescriptor asociado a la operacin se establece en Unchanged y los
nuevos valores se combinan mediante OverwriteChanges. Cuando una operacin de insercin,
actualizacin o eliminacin produce un error en el servicio de datos, el estado de la entidad permanece
como estaba antes de que se llamara al mtodo SaveChanges y la propiedad Error de OperationResponse
se establece en una instancia de DataServiceRequestException que contiene informacin sobre el error.

Establecer el mtodo HTTP para las actualizaciones


De forma predeterminada, la biblioteca cliente de .NET Framework enva actualizaciones a las entidades
existentes como solicitudes MERGE. Una solicitud MERGE actualiza las propiedades seleccionadas de la
entidad; sin embargo, el cliente siempre incluye todas las propiedades en la solicitud MERGE, incluso las
propiedades que no hayan cambiado. El protocolo OData tambin admite el envo de solicitudes PUT para
actualizar las entidades. En una solicitud PUT, una entidad existente se reemplaza bsicamente por una
nueva instancia de la entidad con valores de propiedad desde el cliente. Para usar las solicitudes PUT,
establezca la marca del objeto ReplaceOnUpdate de la enumeracin SaveChangesOptions cuando se llame
a SaveChanges.
Nota:
Una solicitud PUT se comportar de forma distinta que una solicitud MERGE cuando el cliente no conozca
todas las propiedades de la entidad. Esto puede ocurrir cuando se proyecte un tipo de entidad en un nuevo
tipo en el cliente. Tambin puede ocurrir cuando se hayan agregado nuevas propiedades a la entidad del
modelo de datos del servicio y la propiedad IgnoreMissingProperties de la clase DataServiceContext se
establezca en true para ignorar tales errores de asignacin de cliente. En estos casos, una solicitud PUT
restablecer las propiedades que desconozca el cliente en sus valores predeterminados.

5.9. Trabajar con datos binarios


La biblioteca de cliente de WCF Data Services le permite recuperar y actualizar los datos binarios de una
fuente Open Data Protocol (OData) de una de las siguientes formas:
Como una propiedad del tipo primitivo de una entidad. Este es el mtodo recomendado para
trabajar con objetos de datos binarios pequeos que se pueden cargar con facilidad en la memoria.
En este caso, la propiedad binaria es una propiedad de entidad expuesta por el modelo de datos y
el servicio de datos serializa los datos binarios como XML codificado binario de base 64 en el
mensaje de respuesta.
Como flujo de recursos binarios independiente. Este es el mtodo recomendado para obtener
acceso y cambiar datos de objetos binarios grandes (BLOB) que pueden representar una foto, un
vdeo o cualquier otro tipo de datos codificados binarios.
WCF Data Services implementa la transmisin por secuencias de datos binarios mediante HTTP como se
define en OData . En este mecanismo, los datos binarios se tratan como recurso multimedia independiente
de una entidad pero est relacionado con ella, que se denomina entrada de vnculo multimedia.
Sugerencia:
Para obtener un ejemplo paso a paso de cmo crear una aplicacin cliente de Windows Presentation
Foundation (WPF) que descargue archivos de imgenes binarias desde un servicio de OData que almacene
fotos, vea la entrada de blog relacionada con la parte 2 del programa de proveedores de transmisin por
secuencias de servicios de datos: acceso a un flujo de recursos multimedia desde el cliente.

Metadatos de entidad
Una entidad que tenga un flujo de recursos multimedia relacionado se indica en los metadatos del servicio
de datos mediante el atributo HasStream aplicado a un tipo de entidad que sea la entrada de vnculo
multimedia. En el siguiente ejemplo, la entidad PhotoInfo es una entrada de vnculo multimedia con un
recurso multimedia relacionado, indicado por el atributo HasStream.

MCT: Luis Dueas

Pag 126 de 128

WCF Data Service


<EntityType xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
Name="PhotoInfo" m:HasStream="true">
<Key>
<PropertyRef Name="PhotoId" />
</Key>
<Property Name="PhotoId" Type="Int32" Nullable="false"
annotation:StoreGeneratedPattern="Identity" />
<Property Name="FileName" Type="String" Nullable="false" />
<Property Name="FileSize" Type="Int32" Nullable="true" />
<Property Name="DateTaken" Type="DateTime" Nullable="true" />
<Property Name="TakenBy" Type="String" Nullable="true" />
<Property Name="DateAdded" Type="DateTime" Nullable="false" />
<Property Name="Exposure" Type="PhotoData.Exposure" Nullable="false" />
<Property Name="Dimensions" Type="PhotoData.Dimensions" Nullable="false" />
<Property Name="DateModified" Type="DateTime" Nullable="false" />
<Property Name="Comments" Type="String" MaxLength="Max"
FixedLength="false" Unicode="true" />
<Property Name="ContentType" Type="String" MaxLength="50" FixedLength="false" Unicode="true" />
</EntityType>

En el resto de los ejemplos de este tema se muestra cmo acceder y cambiar el flujo de recursos
multimedia.

Acceder al flujo de recursos binarios


La biblioteca cliente de WCF Data Services proporciona mtodos para acceder a flujos de recursos binarios
desde un servicio de datos basado en OData . Cuando se descarga un recurso multimedia, puede usar el
URI de dicho recurso u obtener un flujo binario que contenga los datos del propio recurso multimedia.
Tambin puede cargar los datos del recurso multimedia como flujo binario.

Obtener el URI del flujo binario


Cuando se recuperan ciertos tipos de recursos multimedia, como imgenes y otros archivos multimedia,
suele ser ms fcil usar el URI del recurso multimedia de la aplicacin que administrar el propio flujo de
datos binarios. Para obtener el URI de un flujo de recursos asociado con una entrada de vnculo multimedia
determinada, debe llamar al mtodo GetReadStreamUri de la instancia de la clase DataServiceContext que
est realizando el seguimiento de la entidad. En el ejemplo siguiente se muestra cmo llamar al mtodo
GetReadStreamUri para obtener el URI de un flujo de recursos multimedia que se use con el fin de crear
una nueva imagen en el cliente:
' Use the ReadStreamUri of the Media Resource for selected PhotoInfo object
' as the URI source of a new bitmap image.
photoImage.Source = New BitmapImage(context.GetReadStreamUri(currentPhoto))

Descargar el flujo de recursos binarios


Al recuperar un flujo de recursos multimedia, es necesario llamar al mtodo GetReadStream de la instancia
de la clase DataServiceContext que est realizando el seguimiento de la entrada de vnculo multimedia.
Este mtodo enva una solicitud al servicio de datos que devuelve un objeto DataServiceStreamResponse,
que tiene una referencia al flujo que contiene el recurso. Use este mtodo cuando la aplicacin necesite el
recurso binario como clase Stream. En el ejemplo siguiente se muestra cmo llamar al mtodo
GetReadStream para recuperar un flujo que se use con el fin de crear una nueva imagen en el cliente:
Nota:
El servicio de datos no establece el encabezado de longitud de contenido del mensaje de respuesta que
contiene el flujo binario. Este valor puede no reflejar la longitud real del flujo de datos binarios.

Cargar un recurso multimedia como flujo

MCT: Luis Dueas

Pag 127 de 128

WCF Data Service


Para insertar o actualizar un recurso multimedia, llame al mtodo SetSaveStream de la instancia de la clase
DataServiceContext que est realizando el seguimiento de la entidad. Este mtodo enva una solicitud al
servicio de datos que contiene el recurso multimedia ledo desde el flujo proporcionado. En el siguiente
ejemplo se muestra cmo llamar al mtodo SetSaveStream para enviar una imagen al servicio de datos:
' Set the file stream as the source of binary stream to send to the data service. The Slug header is the file name and
' the content type is determined from the file extension. A value of 'true' means that the stream is closed by the client when
' the upload is complete.
context.SetSaveStream(photoEntity, imageStream, True, photoEntity.ContentType, photoEntity.FileName)

En este ejemplo, se llama al mtodo SetSaveStream proporcionando un valor true para el parmetro
closeStream. De esta forma, se garantiza que la clase DataServiceContext cierre el flujo una vez cargados
los datos binarios en el servicio de datos.
Nota:
Cuando llame al mtodo SetSaveStream, el flujo no se enva al servicio de datos hasta que se llame al
mtodo SaveChanges.

MCT: Luis Dueas

Pag 128 de 128

Você também pode gostar