Académique Documents
Professionnel Documents
Culture Documents
Pag 1 de 128
Customers('ALFKI')/Orders?$filter=Freight gt 50 filtra los recursos para devolver solo los pedidos cuyo
costo de flete sea mayor que 50 dlares.
Independencia de almacenamiento
MCT: Luis Dueas
Pag 2 de 128
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.
Pag 3 de 128
Pag 4 de 128
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.
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')
Pag 5 de 128
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'
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
http://services.odata.org/Northwind/Northwind.svc/Customers?$orderby=Country,City
$top
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:
Pag 6 de 128
$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
http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders?
$expand=Order_Details
$format
$select
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
Pag 7 de 128
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.
Pag 8 de 128
2.
3.
4.
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).
b.
Pag 9 de 128
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.
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)
Pag 10 de 128
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.
2.
3.
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.
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.
Pag 11 de 128
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.
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.
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}" />
Pag 12 de 128
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.
Para tener acceso a los datos del servicio de datos en la aplicacin WPF
1.
2.
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")
Pag 13 de 128
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
3.
Pag 14 de 128
Pag 15 de 128
Pag 16 de 128
AcceptProjectionRequests
EnableTypeAccess
EnableTypeConversion
MaxChangesetCount
MaxExpandCount
MaxExpandDepth
MaxObjectCountOnInsert
MaxProtocolVersion
MaxResultsPerCollection
RegisterKnownType
SetEntitySetAccessRule
SetEntitySetPageSize
Pag 17 de 128
UseVerboseErrors
/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
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
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.
Pag 19 de 128
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
Pag 20 de 128
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.
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)
Pag 21 de 128
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.
Pag 22 de 128
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
Proveedores de
servicios de datos
personalizados
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.
Pag 23 de 128
Para agregar un modelo de Entity Framework que est basado en una base de
datos existente a una aplicacin web existente
1.
2.
3.
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.
9.
Pag 24 de 128
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.
Pag 25 de 128
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.
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 .
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.
ClearChanges
Pag 26 de 128
DeleteResource
GetResource
GetValue
ResolveResource
SaveChanges
SetReference
SetValue
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.
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.
Pag 27 de 128
Pag 28 de 128
Pag 29 de 128
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.
6.
7.
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
Pag 30 de 128
Pag 31 de 128
Pag 32 de 128
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.
Descripcin
Proveedor de
metadatos
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
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
Pag 33 de 128
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.
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.
5.
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.
Pag 34 de 128
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.
DeleteStream
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
Pag 35 de 128
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
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
Pag 36 de 128
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>
Pag 37 de 128
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.
Pag 38 de 128
IEnumerable
IQueryable
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].
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.
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.
Pag 39 de 128
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
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.
2.
Pag 40 de 128
3.
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
Pag 41 de 128
Pag 42 de 128
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.
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
Pag 43 de 128
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.
FC_ContentKind
Pag 44 de 128
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.
Pag 45 de 128
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>
Pag 46 de 128
Pag 47 de 128
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" />
Pag 48 de 128
4.
5.
6.
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>
Pag 49 de 128
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, _
Pag 50 de 128
Pag 51 de 128
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
Pag 53 de 128
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.
Pag 54 de 128
2.
3.
2.
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
Pag 55 de 128
2.
3.
Pag 56 de 128
2.
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 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.
Pag 57 de 128
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.
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.
Pag 58 de 128
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.
Pag 59 de 128
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
Autenticacin
basada en
notificaciones
Pag 60 de 128
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.
Pag 61 de 128
Pag 62 de 128
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.
Pag 63 de 128
Versin 2
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
Pag 64 de 128
Pag 65 de 128
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
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
/language:[VB|CSharp]
/nologo
/out: <archivo>
Especifica el nombre del archivo de cdigo fuente que contiene las clases de
servicio de datos de cliente generadas.
/uri: <string>
/version:[1.0|2.0]
4.
Pag 67 de 128
Nota:
Debe reemplazar el valor proporcionado para el parmetro /uri: con el URI de la instancia del
servicio de datos de ejemplo de Northwind.
Pag 68 de 128
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.
Pag 69 de 128
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
Pag 70 de 128
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
Pag 71 de 128
Pag 72 de 128
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
Admitida
Admitida
.City = c.City, _
.Region = c.Region, _
.PostalCode = c.PostalCode, _
.Country = c.Country}
Pag 73 de 128
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)
Pag 74 de 128
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"
Pag 75 de 128
Pag 76 de 128
Pag 77 de 128
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
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.
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
' Define a query for orders with a Freight value greater than 30.
Dim filteredOrders = context.Orders.AddQueryOption("$filter", "Freight gt 30M")
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
Pag 79 de 128
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
}
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" .
Pag 80 de 128
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
http://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details .
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
Pag 81 de 128
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
Pag 82 de 128
1.
Empty
2.
Range
3.
Repeat
4.
ToDictionary
5.
ToLookup
Contains
EndsWith
IndexOf
Length
Replace
Substring
Substring
ToLower
ToUpper
Trim
Hour
Minute
Month
Second
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
Ceiling
Floor
Floor
Round
Round
Pag 83 de 128
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.
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 complejas se establecen en una nueva instancia de tipo complejo, que se
establecen con las propiedades del tipo complejo de la respuesta.
Pag 84 de 128
4.
5.
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
Pag 85 de 128
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.
Pag 86 de 128
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
Pag 87 de 128
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
Pag 88 de 128
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.
Pag 89 de 128
Pag 90 de 128
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
Pag 91 de 128
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.
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
Pag 92 de 128
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
Pag 93 de 128
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
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
Pag 94 de 128
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
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.
Pag 95 de 128
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
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.
Pag 96 de 128
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
Pag 97 de 128
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)
Pag 98 de 128
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()
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
AttachLink
Pag 99 de 128
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
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()
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"
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") _
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
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
Mtodos
BeginExecute
EndExecute
BeginExecute
EndExecute
BeginExecuteBatch
EndExecuteBatch
BeginLoadProperty
EndLoadProperty
BeginSaveChanges
EndSaveChanges
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
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
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
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"/>
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.
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.
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)
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)
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:
4.
Un control Label.
Un
segundo
elemento
CollectionViewSource
denominado
5.
6.
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.
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.
En la ventana Orgenes de datos, expanda el nodo Customers del origen de datos del proyecto
NorthwindEntities.
2.
Un control Label.
3.
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.
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.
9.
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
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
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.
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.
En el resto de los ejemplos de este tema se muestra cmo acceder y cambiar el flujo de recursos
multimedia.
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.