Compartir a través de


Flujo de ejecución de LINQ to Entities

Las consultas con Entity Framework se representan mediante consultas de árboles de comandos, que se ejecutan en el contexto del objeto. LINQ to Entities convierte las consultas de Language-Integrated Queries (LINQ) en consultas de árboles de comandos, ejecuta las consultas en Entity Framework y devuelve objetos que se pueden usar tanto en Entity Framework como en LINQ. A continuación se muestra el proceso para crear y ejecutar una consulta de LINQ to Entities.

  1. Cree una instancia de ObjectQuery en ObjectContext.

  2. Cree una consulta de LINQ to Entities en C# o Visual Basic con la instancia de ObjectQuery.

  3. Convierta los operadores y expresiones de consulta estándar de LINQ en árboles de comandos.

  4. Ejecute la consulta, con representación de un árbol de comandos, en el origen de datos. Las excepciones producidas en el origen de datos durante la ejecución se pasan directamente al cliente.

  5. Devuelva los resultados de la consulta al cliente.

Crear una instancia de ObjectQuery

La clase ObjectQuery genérica representa una consulta que devuelve una colección de cero o más entidades con tipo. Una consulta de objetos se suele crear a partir de un contexto del objeto existente, en lugar de crearse de forma manual, y siempre pertenece a dicho contexto. Este contexto proporciona la información de metadatos y de la conexión necesaria para crear y ejecutar la consulta. La clase genérica ObjectQuery implementa la interfaz genérica IQueryable, cuyos métodos de generador permiten que las consultas de LINQ se generen de forma gradual.

Crear la consulta

Las instancias de la clase genérica ObjectQuery, que implementa la interfaz genérica IQueryable, actúan como origen de datos para las consultas de LINQ to Entities. En una consulta se especifica exactamente la información que se desea recuperar del origen de datos. Una consulta también puede especificar cómo se debe ordenar, agrupar y conformar esa información antes de que se devuelva. En LINQ, una consulta se almacena en una variable. Esta variable de consulta no realiza ninguna acción y no devuelve datos; solamente almacena la información de la consulta. Tras crear una consulta debe ejecutarla para recuperar los datos.

Las consultas de LINQ to Entities se pueden formular en dos sintaxis diferentes: sintaxis de expresiones de consulta y sintaxis de consultas basadas en métodos. La sintaxis de expresiones de consulta y la sintaxis de consultas basadas en métodos son una novedad de C# 3.0 y Visual Basic 9.0.

Para obtener más información, vea Consultas en LINQ to Entities.

En el ejemplo siguiente de sintaxis de expresiones de consulta se crea una instancia de ObjectQuery del contexto del objeto de AdventureWorks y se usa Select para devolver todas las filas de Product.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames =
       from p in products
       select p;
}

En el ejemplo siguiente de sintaxis de consultas basadas en métodos se crea una instancia de ObjectQuery del contexto del objeto de AdventureWorks y se usa Select para devolver todas las filas de Product.

Using AWEntities As New AdventureWorksEntities


    Dim productNames = AWEntities.Product.Select(Function(p) p.Name)

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames = products.Select(p => p);

}

Conversión de las consultas

Para ejecutar una consulta de LINQ to Entities en Entity Framework, se debe convertir a una representación de árbol de comandos que se pueda ejecutar en Entity Framework.

Las consultas de LINQ to Entities están compuestas de operadores de consulta estándar de LINQ (como Select, Where y GroupBy) y expresiones (x > 10, Contact.LastName, etcétera). Los operadores de LINQ no se definen en una clase, sino que son los métodos de una clase. En LINQ, las expresiones pueden contener todo lo que permitan los tipos dentro del espacio de nombres System.Linq.Expressions y, por extensión, todo lo que se pueda representar en una función lambda. Se trata de un superconjunto de las expresiones permitidas por Entity Framework, que, por definición, están restringidas a las operaciones admitidas tanto en la base de datos como por ObjectQuery.

En Entity Framework, tanto los operadores como las expresiones se representan mediante una jerarquía de tipos simple, que después se coloca en un árbol de comandos. Entity Framework usa el árbol de comandos para ejecutar la consulta. Si la consulta de LINQ no se puede expresar como un árbol de comandos, se producirá una excepción cuando se convierta la consulta. La conversión de las consultas de LINQ to Entities implica dos conversiones más: la de los operadores de consulta estándar y la de las expresiones.

Hay varios operadores de consulta estándar de LINQ que no tienen una conversión válida en LINQ to Entities. Si se intenta usar estos operadores, se producirá una excepción al convertir la consulta. Para obtener una lista de los operadores de LINQ to Entities admitidos, vea Métodos admitidos y no admitidos (LINQ to Entities).

Para obtener más información sobre cómo usar los operadores de consulta estándar en LINQ to Entities, vea Operadores de consulta estándar en las consultas de LINQ to Entities.

En general, las expresiones de LINQ to Entities se evalúan en el servidor, de modo que es previsible que el comportamiento de la expresión no siga la semántica de CLR. Para obtener más información, vea Expresiones en consultas de LINQ to Entities.

Ejecución de la consulta

Una vez que el usuario crea una consulta de LINQ, esta se convierte en una representación compatible con Entity Framework (en forma de árboles de comandos), que después se ejecuta en el origen de datos. En el momento de ejecutar la consulta, todas las expresiones de consulta (o sus componentes) se evalúan en el cliente o en el servidor. Esto incluye las expresiones que se usan en la materialización resultante o en las proyecciones de entidades.

El momento en que se ejecuta una expresión de una consulta puede variar. Las consultas de LINQ se ejecutan siempre que se recorre en iteración la variable de la consulta, no cuando se crea la citada variable; esto se conoce como ejecución aplazada. También se puede obligar a que la consulta se ejecute inmediatamente, lo que es útil para almacenar en caché los resultados de la consulta. En el ejemplo siguiente se usa Select para devolver todas las filas de Product y mostrar los nombres de producto. Al recorrer en iteración la variable de la consulta en un bucle foreach/For Each, se provoca la ejecución de la consulta.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p.Name

    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames =
       from p in products
       select p.Name;

    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

Cuando se ejecuta una consulta de LINQ to Entities, algunas de sus expresiones podrían ejecutarse en el servidor y ciertas partes podrían ejecutarse de forma local en el cliente. La evaluación en el cliente de una expresión se lleva a cabo antes de ejecutar la consulta en el servidor. Si una expresión se evalúa en el cliente, el resultado de esa evaluación se sustituye por la expresión en la consulta, y ésta se ejecuta entonces en el servidor. Dado que las consultas se ejecutan en el origen de datos, la configuración de este invalida el comportamiento especificado en el cliente. Algunos ejemplos de esto son el tratamiento de los valores Null y la precisión numérica. Cualquier excepción que se produzca durante la ejecución de la consulta en el servidor se pasa directamente al cliente. Para obtener más información, vea Ejecución de la consulta.

Materialización

La materialización es el proceso por el que se devuelven los resultados de la consulta al cliente en forma de tipos de CLR. En LINQ to Entities, los registros de datos de los resultados de las consultas no se devuelven nunca; siempre hay un tipo de CLR correspondiente, definido por el usuario o por Entity Framework, o generado por el compilador (tipos anónimos). Entity Framework realiza la materialización de todos los objetos. Los errores derivados de la incapacidad de encontrar una correspondencia entre Entity Framework y CLR hará que se produzcan excepciones durante la materialización de los objetos.

Los resultados de las consultas se suelen devolver en forma de alguno de los elementos siguientes.

  • Una colección con cero o más objetos de entidad con tipo o una proyección de tipos complejos en el EDM.

  • Tipos de CRL admitidos por el EDM.

  • Colecciones insertadas.

  • Tipos anónimos.

Para obtener más información, vea Resultados de la consulta.

Vea también

Otros recursos

Consultar con LINQ to Entities