Este artículo proviene de un motor de traducción automática.

Puntos de datos

Consultas de proyección y alternativas de LINQ en servicios WCF

Julie Lerman

Descargar el código de ejemplo

Julie LermanEl moderador en mi grupo de usuarios .NET local estaba escribiendo una consulta LINQ durante su sesión mes pasado cuando le pregunté le, “ How nunca vivimos sin LINQ? ” “ No tengo ninguna idea ”, contestó.

Es verdad. Desde que se presentó en Visual Studio 2008, LINQ ha realizado tales una diferencia en cómo nos código en Microsoft .NET Framework. En combinación con las muchas nuevas características de lenguaje que se introdujeron en Visual Basic y C#, es un solver problema consistente para consultar orígenes de datos y objetos en memoria.

Una de las capacidades de LINQ que es una bendición y una fuente ocasional de frustración es que pueden proyectarse aleatoriamente con forma de datos en tipos anónimos. Cuando simplemente necesita tomar una vista especial de los datos sin tener que declarar una nueva clase para este tipo throwaway, tipos anónimos son una gran solución. Las proyecciones de LINQ y tipos anónimos ciertamente han dañado nos. ¿Por lo que por qué digo también pueden ser una fuente de frustración?

Si alguna vez ha utilizado una proyección de LINQ en un método debe devolver datos a otro método, o peor, utilizan una proyección de LINQ en una operación de servicio de Windows Communication Foundation (WCF), es posible que entiendan.

Dado que los tipos anónimos son tipos throwaway, no tener ninguna declaración y se entiende sólo dentro del método donde se crean. Si escribe una consulta que devuelve una lista de tipos anónimos, no hay ninguna forma de definir un método ar gument decir “ voy a devolver una lista de … ” porque no hay ninguna manera de expresar “ … de tipos anónimos. ”

Ésta es una consulta LINQ a Entities con una proyección simple:

var custQuery = from c in context.Customers

                 select new {c.CustomerID, Name=c.LastName.Trim() + 

                 ", " + c.FirstName};

En tiempo de ejecución, la variable custQuery realmente será un f__AnonymousType0 de <<>ObjectQuery <int,string> >.

La var (y el uso de Visual Basic Dim alternativo) nos irse con no tener (o que necesitan) permiten una forma de expresar este tipo.

Si desea devolver los resultados de esa consulta desde un método, la solución razonable sólo es crear una clase para representar el tipo que se devuelven. Sin embargo, de esta manera, procesa la belleza de discutible tipo anónimo. Ahora tiene que escribir más código, definir clases y (posiblemente) nuevos proyectos para albergar las nuevas clases, asegúrese de que los distintos ensamblados mediante estas clases tienen acceso a ellos y así sucesivamente.

Hasta hace poco, servicios de datos proporcionan un acertijo adicional. En orden de los datos del proyecto, había que crear una operación personalizada en un servicio, ejecutar su propia consulta y devolver algún tipo de clase predefinido entendió el cliente.

Cuando se trabaja con los servicios, hay muchas situaciones donde desea trabajar con una vista determinada de datos sin pagar el precio de mover tipos mayores a través del cable.

Aparentemente, hay más opciones además de crear un tipo adicional en su dominio para satisfacer esta necesidad temporal.

Nueva capacidad de proyección en WCF Data Services

La actualización de servicios de datos para .NET Framework 3.5 SP1 presenta unas cuantas características eficaces para WCF Data Services, que también forman parte de .NET Framework 4. Entre estas características es la capacidad de utilizar proyecciones en las consultas contra los servicios de datos. Recomiendo encarecidamente desprotegiendo el blog equipo servicios de WCF de datos en todos los que es nueva en esta actualización de blogs.msdn.com/astoriateam/Archive/2010/01/27/Data-Services-Update-for-NET-3-5-SP1-Available-for-Download.aspx.

El operador seleccione $ se ha agregado a la sintaxis de URI de servicios de datos. Permite incluso proyección de propiedad de navegación y propiedad.

Aquí es un ejemplo sencillo de una proyección obtiene Propiedades escalares unas para un cliente junto con la propiedad de navegación SalesOrderHeaders:

http://localhost /DataService.svc/Customers(609)
  $select=CustomerID,LastName,FirstName,SalesOrderHeaders&$expand=
  SalesOrderHeaders

El operador de expansión obliga a incluir no sólo un vínculo a los pedidos, pero los datos para cada pedido así los resultados.

La figura 1 muestra los resultados de esta consulta. El SalesOrderHeaders expandido (que contiene sólo un único pedido) se resaltan en amarillo y la información del cliente se resalta en verde.

Figure 1 Results of a Data Services Query Projection Requesting Three Customer Properties and the Customer’s SalesOrder-Headers
Figura 1 Resultados de una proyección de consultas de Data Services solicitar SalesOrderHeaders del cliente y tres propiedades de Customer

LINQ en función de REST de .NET Framework y las API para servicios de WCF de datos de cliente de Silverlight se ha actualizado para permitir que las proyecciones así:

var projectedCust = (from c in context.Customers

                    where c.CustomerID==609

                    select new {c.CustomerID, c.LastName})

                    .FirstOrDefault();

ProjectedCust ahora es un tipo anónimo que puedo utilizar en mi aplicación de cliente.

También es posible a un proyecto en tipos de entidad conocida y en algunos casos, el DataContext puede realizar un seguimiento de los cambios realizados por el cliente y se pueden conservar estos cambios a través SaveChanges método del servicio. Ser consciente de que las propiedades que faltan obtener llenará con sus valores predeterminados (o null si lo acepta valores NULL) y almacena en la base de datos.

Habilitar a tipos de seguros previstas desde un EDM

Si está usando un Entity Framework Entity Data Model (EDM), hay una forma cómoda para evitar que se está conforme con tipos anónimos cuando es necesario pasar fuera del método en el que se crearon.

El EDM tiene una asignación denominada QueryView. He apuntado a muchos clientes esto en el pasado, anteriores a la compatibilidad con proyección de servicios de datos. No sólo sigue lo solucionarse perfectamente los servicios de datos, pero para servicios de WCF y servicios de RIA personalizado también.

¿Qué es un QueryView? Es un tipo especial de asignación en los metadatos de Entity Framework. Normalmente, asignar propiedades de una entidad a las tablas de bases de datos o ver las columnas tal como está descritas en el modelo de almacén: lenguaje de definición de esquemas de almacenamiento (SSDL) — de metadatos, como se muestra en Figura 2.

Figure 2 Mapping Table Columns Directly to Entity Properties
Figura 2 Columnas de tabla de asignación directamente a propiedades de entidad

QueryView, sin embargo, le permite crear una vista a través de esas columnas de la tabla SSDL en lugar de asignan directamente a ellos. Existen muchas razones para utilizar un QueryView. Algunos ejemplos son: para exponer las entidades como lectura - sólo, para entidades de filtros de modo condicional que no permite la asignación o para proporcionar distintas vistas de las tablas de datos de la base de datos.

Es el último de estos propósitos que me centraré en como una alternativa a los tipos anónimos que encuentra con frecuencia personalmente a proyectar en la aplicación. Un ejemplo sería una lista de picking. ¿Por qué un cliente todo tipo de valor devuelto para una lista desplegable que necesita sólo un ID y el nombre del cliente?

Creación de un QueryView

Antes de crear un QueryView, debe crear una entidad en el modelo que representa la forma de la vista que se propone, por ejemplo, la entidad CustomerNameAndID.

Pero no se puede asignar esta entidad directamente a la tabla de cliente en el SSDL. Asignación de la entidad de cliente y la entidad CustomerNameAndID a la columna de la tabla CustomerID crearía un conflicto.

En su lugar, simplemente modo que puede crear una vista de una tabla en la base de datos, puede crear una vista del cliente SSDL directamente en los metadatos. Un QueryView es, literalmente, una expresión de Entity SQL sobre el SSDL. Se trata de parte de los metadatos de idioma (MSL) de asignación especificación del modelo. No hay ninguna compatibilidad diseñador crear QueryView, por lo que tendrá que escribir directamente en el código XML.

Puesto que va a asignar al esquema de almacén de la tabla, que parece una buena idea de qué que vea. Figura 3 enumera la descripción de SSDL de la tabla de base de datos de cliente que tiene una apariencia similar a la entidad de cliente en los metadatos del modelo conceptual, excepto para el uso de tipos de datos del proveedor.

Figura 3 La descripción de SSDL de la tabla de base de datos de cliente

<EntityType Name="Customer">

  <Key>

    <PropertyRef Name="CustomerID" />

  </Key>

  <Property Name="CustomerID" Type="int" Nullable="false"

            StoreGeneratedPattern="Identity" />

  <Property Name="Title" Type="nvarchar" MaxLength="8" />

  <Property Name="FirstName" Type="nvarchar" Nullable="false" 

            MaxLength="50" />

  <Property Name="MiddleName" Type="nvarchar" MaxLength="50" />

  <Property Name="LastName" Type="nvarchar" Nullable="false" 

            MaxLength="50" />

  <Property Name="Suffix" Type="nvarchar" MaxLength="10" />

  <Property Name="CompanyName" Type="nvarchar" MaxLength="128" />

  <Property Name="SalesPerson" Type="nvarchar" MaxLength="256" />

  <Property Name="EmailAddress" Type="nvarchar" MaxLength="50" />

  <Property Name="Phone" Type="nvarchar" MaxLength="25" />

  <Property Name="ModifiedDate" Type="datetime" Nullable="false" />

  <Property Name="TimeStamp" Type="timestamp" Nullable="false"

            StoreGeneratedPattern="Computed" />

</EntityType>

Otro elemento importante para el QueryView será espacio de nombres del esquema de almacén, ModelStoreContainer. Ahora dispone de las partes necesarias para construir la expresión QueryView. Éste es un QueryView que proyectos los tres campos obligatorios desde el SSDL en la entidad CustomerNameAndID que creé en el modelo:

SELECT VALUE AWModel.CustomerNameAndID(c.CustomerID, c.FirstName, 

        c.LastName) FROM ModelStoreContainer.Customer as c

Traducir Entity SQL para inglés: “ Consulta al cliente en el esquema de almacén, tire hacia fuera de estas tres columnas y asígneles volver a mí como una entidad CustomerNameAndID. ” AWModel es el espacio de nombres del contenedor de entidad del modelo conceptual. Es obligatorio utilizar los nombres de tipos del lenguaje de definición de esquemas conceptuales (CSDL) y el SSDL que se hace referencia en la expresión con establecimiento inflexible de tipos.

Siempre que los resultados de la proyección (un entero, una cadena y una cadena) coinciden con el esquema de la entidad de destino, se realizará correctamente la asignación. He intentado utilizar concatenación dentro de la proyección y funciones — por ejemplo, (c.CustomerID, c.FirstName + c.LastName)—but Esto produce un error que indica que no se permiten funciones. Por lo tanto, estoy obligado a utilice las propiedades FirstName y LastName y dejar que el cliente encargarse de concatenación.

Colocar el QueryView en los metadatos

Debe colocar la expresión QueryView dentro del elemento EntitySetMapping para la entidad que se introducirá en EntityContainerMapping en los metadatos. Figura 4 muestra este QueryView (resaltado en amarillo) en el código XML sin formato del archivo mi EDMX.

Figure 4 A QueryView in the Mappings Section

Figura 4 QueryView en la sección de asignaciones

Ahora mi CustomerNameAndID forma parte de Mi modelo y estará disponible para ningún consumidor. Y hay otra ventaja de la QueryView. Aunque el objetivo de este QueryView es crear una lista de referencia de sólo lectura, también puede actualizar las entidades se asignan mediante QueryViews. El contexto realizará un seguimiento de cambios en objetos CustomerNameAndID. Aunque no es capaz de generar automáticamente Insertar, actualizar y eliminar comandos para esta entidad Entity Framework, puede asignar procedimientos almacenados.

Obteniendo los beneficios de la QueryView

Ahora que tiene el QueryView en el modelo, no es necesario dependen de las proyecciones o tipos anónimos para recuperar estas vistas de sus datos. En los servicios de datos de WCF, CustomerNameAndIDs se convierte en un conjunto de entidad válido a consulta contra, tal como se muestra aquí:

List<CustomerNameAndID> custPickList = 

  context.CustomerNameAndIDs.ToList();

Sin líos proyecciones. Mejor aún, puede crear operaciones de servicio en los servicios de WCF personalizados que ahora pueden devolver este objeto con establecimiento inflexible de tipos sin tener que definir nuevos tipos en su aplicación y el proyecto en ellos.

public List<CustomerNameAndID> GetCustomerPickList()

    {

      using (var context = new AWEntities())

      {

        return context.CustomerNameAndIDs.OrderBy(

          c => c.LastName).ToList();

      }

    }

Debido a de la limitación que nos impide concatenar nombres y apellidos en el QueryView es los desarrolladores que consumen el servicio para realizar esta concatenación en su extremo.

Servicios de WCF RIA también pueden beneficiarse de la QueryView. Es posible que desee exponer un método para recuperar una lista de picking restaurante procedente del servicio de dominio. En lugar de tener que crear una clase adicional en el servicio de dominio para representar las propiedades proyectadas, esta entidad RestaurantPickList está respaldada por QueryView en el modelo, lo que facilita proporcionar estos datos:

public IQueryable<RestaurantPickList> GetRestaurantPickList()

    {

      return context.RestaurantPickLists;

    }

QueryViews o previsiones, nos hemos obtenido se cubiertos

Tener la capacidad de las vistas de proyecto a través de los tipos de datos es una enorme ventaja en consultas y es una excelente incorporación a los servicios de datos de WCF. Aun así, hay ocasiones cuando tengan acceso a estas vistas, sin necesidad de proyecto y sin tener que preocuparse acerca de cómo compartir el resultado simplificará algunas de las tareas de codificación.

Una última Nota: Con la introducción de las claves externas de la versión de .NET Framework 4 de Entity Framework QueryView elegir listas hacer incluso más sentido ya que se pueden devolver las entidades de sólo lectura y simplemente utilizar sus propiedades para actualizar las propiedades de clave externas en las entidades que está editando.  

Julie Lerman es MVP de Microsoft, profesora de .NET y consultora que vive en las colinas de Vermont. Puede encontrar su presentación sobre acceso a datos y otros temas de Microsoft .NET en grupos de usuarios y conferencias en todo el mundo. Lerman mantiene un blog en thedatafarm.com/blog y es la autora del célebre libro, “Programming Entity Framework” (O’Reilly Media, 2009). Siga su en Twitter: julielerman.

Gracias al siguiente técnico experto para revisar este artículo: Alex James