Consultar el servicio de datos (WCF Data Services)

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

Consultas del servicio de datos

La clase DataServiceQuery genérica representa una consulta que devuelve una colección de cero o más instancias de tipo de entidad. Una consulta del servicio de datos siempre pertenece al contexto de un servicio de datos existente. Este contexto mantiene la información necesaria del URI del servicio y la de los metadatos para crear y ejecutar la consulta.

Cuando se usa el cuadro de diálogo Agregar referencia de servicio para agregar un servicio de datos a una aplicación cliente basada en .NET Framework, se crea una clase de contendor de entidades que hereda de la clase DataServiceContext. Esta clase incluye propiedades que devuelven instancias de DataServiceQuery con tipo. Existe una propiedad para cada conjunto de entidades que expone el servicio de datos. Estas propiedades facilitan la creación de una instancia de DataServiceQuery con tipo.

Las consultas se ejecutan en los escenarios siguientes:

  • Cuando se enumeran los resultados implícitamente, por ejemplo:

    • Cuando se enumera una propiedad de la clase DataServiceContext que representa un conjunto de entidades, como ocurre en un bucle foreach (C#) o For Each (Visual Basic).

    • Cuando se asigna la consulta a una colección List.

  • Cuando se llama explícitamente a los métodos Execute o BeginExecute.

  • Cuando se llama a un operador de ejecución de consultas LINQ, como First o Single.

Cuando se ejecuta la siguiente consulta, devuelve todas las entidades Customers del servicio de datos de Northwind:

' Define a new query for Customers.
Dim query As DataServiceQuery(Of Customer) = context.Customers
// Define a new query for Customers.
DataServiceQuery<Customer> query = context.Customers;

Para obtener más información, vea Cómo: Ejecutar consultas en el servicio de datos (WCF Data Services).

El cliente de WCF Data Services admite consultas para objetos enlazados en tiempo de ejecución, 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 dinámicos 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 expresión 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 más de 30 dólares 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
var selectedOrders = from o in context.Orders
                     where o.Freight > 30
                     orderby 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 rápido basado en Northwind:

https://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30
Dd673933.note(es-es,VS.100).gifNota:
El conjunto de consultas que se pueden expresar en la sintaxis de LINQ es más 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 ningún URI del servicio de datos de destino, se produce una excepción NotSupportedException.

Para obtener más información, vea Consideraciones sobre LINQ (Servicios de datos de WCF).

Agregar opciones de consulta

Las consultas del servicio de datos admiten todas las opciones de consulta que proporciona WCF Data Services . Llame al método AddQueryOption para anexar las opciones de consulta a una instancia de la clase DataServiceQuery. El método AddQueryOption devuelve una nueva instancia de la clase DataServiceQuery que es equivalente a la consulta original pero con un conjunto de opciones de consulta nuevo. Cuando se ejecuta la siguiente consulta, devuelve el valor Orders filtrado por el valor Freight y ordenado por OrderID, en orden descendente:

' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = context.Orders _
.AddQueryOption("$filter", "Freight gt 30") _
.AddQueryOption("$orderby", "OrderID desc")
// Define a query for orders with a Freight value greater than 30
// and that is ordered by the ship date, descending.
DataServiceQuery<Order> selectedOrders = context.Orders
    .AddQueryOption("$filter", "Freight gt 30")
    .AddQueryOption("$orderby", "OrderID desc");

Puede usar la opción 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
// Create the DataServiceContext using the service URI.
NorthwindEntities 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.
DataServiceQuery<Order> selectedOrders = context.Orders
    .AddQueryOption("$orderby", "Freight gt 30 desc");

try
{
    // Enumerate over the results of the query.
    foreach (Order order in selectedOrders)
    {
        Console.WriteLine("Order ID: {0} - Freight: {1}",
            order.OrderID, order.Freight);
    }
}
catch (DataServiceQueryException ex)
{
    throw new ApplicationException(
        "An error occurred during query execution.", ex);
}

Puede llamar al método AddQueryOption consecutivamente para construir expresiones de consulta complejas. Para obtener más información, vea Cómo: Agregar opciones de consulta a una consulta de servicio de datos (WCF Data Services).

Las opciones de consulta le proporcionan otra forma de expresar los componentes estáticos de una consulta LINQ. Para obtener más información, vea Consideraciones sobre LINQ (Servicios de datos de WCF).

Dd673933.note(es-es,VS.100).gifNota:
La opción de consulta $select no se puede agregar a ningún URI de la consulta mediante el uso del método AddQueryOption. Se recomienda usar el método Select de LINQ para que el cliente genere la opción de consulta $select en el URI de solicitud.

Ejecución de cliente frente a servidor

El cliente ejecuta una consulta en dos partes. Siempre que sea posible, las expresiones de una consulta primero se evalúan en el cliente y, a continuación, se generan y se envían al servicio de datos para su evaluación en los datos del servicio. Considere la siguiente consulta LINQ:

Dim basePrice As Integer = 100
Dim discount As Decimal = Convert.ToDecimal(0.1)

' Define a query that returns products based on a 
' calculation that is determined on the client.
Dim productsQuery = From p In context.Products
                  Where p.UnitPrice >
                  (basePrice - (basePrice * discount)) AndAlso
                  p.ProductName.Contains("bike")
                  Select p
int basePrice = 100;
decimal discount = .10M;

// Define a query that returns products based on a 
// calculation that is determined on the client.
var productsQuery = from p in context.Products
                  where p.UnitPrice >
                  (basePrice - (basePrice * discount)) &&
                  p.ProductName.Contains("bike")
                  select p;

En este ejemplo, la expresión (basePrice – (basePrice * discount)) se evalúa en el cliente. Por ello, el URI de la consulta real https://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and substringof('bike',ProductName) que se envía al servicio de datos contiene el valor decimal ya calculado de 90 en la cláusula de filtro. El resto de las partes de la expresión de filtrado, incluida la expresión de subcadena, las evalúa el servicio de datos. Las expresiones que se evalúan en el cliente siguen la semántica de Common Language Runtime (CLR), mientras que las expresiones enviadas al servicio de datos confían en la implementación del servicio de datos del protocolo OData . Debe tener en cuenta los escenarios en los que esta evaluación independiente pueda causar resultados inesperados, como cuando tanto el cliente como el servidor realicen evaluaciones basadas en la hora en distintas zonas horarias.

Respuestas de consulta

Cuando se ejecuta, el objeto DataServiceQuery devuelve una interfaz IEnumerable del tipo de entidad solicitado. Este resultado de consulta se puede convertir en un objeto QueryOperationResponse, como en el siguiente ejemplo:

' Execute the query for all customers and get the response object.
Dim response As QueryOperationResponse(Of Customer) = _
    CType(query.Execute(), QueryOperationResponse(Of Customer))
// Execute the query for all customers and get the response object.
QueryOperationResponse<Customer> response = 
    query.Execute() as QueryOperationResponse<Customer>;

Las instancias de tipo de entidad que representan entidades del servicio de datos se crean en el cliente mediante un proceso denominado materialización de objetos. Para obtener más información, vea Materialización de objetos (WCF Data Services). El objeto QueryOperationResponse implementa IEnumerable para proporcionar acceso a los resultados de la consulta.

QueryOperationResponse también tiene los siguientes miembros que le permiten tener acceso a información adicional sobre el resultado de una consulta:

  • La propiedad Error: obtiene un error provocado por la operación, si se ha producido alguna.

  • La propiedad Headers: contiene una colección de encabezados de respuesta HTTP asociados con la respuesta de la consulta.

  • La propiedad Query: obtiene el objeto DataServiceQuery original generado por QueryOperationResponse.

  • La propiedad StatusCode: obtiene el código de respuesta HTTP para la respuesta de la consulta.

  • La propiedad TotalCount: obtiene el número total de entidades establecidas cuando se llamó al método IncludeTotalCount en DataServiceQuery.

  • La propiedad GetContinuation: devuelve un objeto DataServiceQueryContinuation que contiene el URI de la siguiente página de resultados.

De forma predeterminada, WCF Data Services solo devuelve los datos seleccionados explícitamente por el URI de la consulta. De esta forma, puede cargar explícitamente datos desde el servicio de datos cuando sea necesario. Se envía una solicitud al servicio de datos cada vez que carga datos explícitamente desde el servicio de datos. Los datos que se pueden cargar explícitamente incluyen entidades relacionadas, datos de respuesta paginados y flujos de datos binarios.

Dd673933.note(es-es,VS.100).gifNota:
Puesto que un servicio de datos puede devolver una respuesta paginada, se recomienda que la aplicación use el modelo de programación para controlar la respuesta paginada de un servicio de datos. Para obtener más información, vea Cargar contenido aplazado (WCF Data Services).

La cantidad de datos devueltos por una consulta también se puede reducir especificando que solo se devuelvan algunas propiedades de una entidad en la respuesta. Para obtener más información, vea Proyecciones de consultas (WCF Data Services).

Obtener un recuento del número total de entidades del conjunto

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

Además, puede obtener el recuento total de entidades del conjunto como valor de las estructuras Int32 o Int64 llamando a los métodos Count o LongCount, respectivamente. Cuando se llama a estos métodos, no se devuelve ningún objeto QueryOperationResponse; solo se devuelve el valor de recuento. Para obtener más información, vea Cómo: Determinar el número de entidades devueltas por una consulta (WCF Data Services).

En esta sección

Proyecciones de consultas (WCF Data Services)

Materialización de objetos (WCF Data Services)

Consideraciones sobre LINQ (Servicios de datos de WCF)

Cómo: Ejecutar consultas en el servicio de datos (WCF Data Services)

Cómo: Agregar opciones de consulta a una consulta de servicio de datos (WCF Data Services)

Cómo: Determinar el número de entidades devueltas por una consulta (WCF Data Services)

Cómo: especificar las credenciales de cliente para una solicitud de servicio de datos (Servicio de datos de WCF)

Cómo: establecer los encabezados en la solicitud de cliente (Servicios de datos de WCF)

Cómo: Proyectar los resultados de una consulta (WCF Data Services)

Vea también

Otros recursos

Biblioteca de cliente de WCF Data Services