Consultas de objeto (Entity Framework)
La clase ObjectQuery genérica representa una consulta que puede devolver una colección de cero o más objetos con tipo. Una ObjectQuery pertenece a un ObjectContext que contiene la información de metadatos y conexión necesaria para crear y ejecutar la consulta. Puede construir una ObjectQuery con un operador new y pasar una cadena de consulta y el contexto del objeto al constructor. Sin embargo, un escenario más común es utilizar propiedades de una clase derivada ObjectContext para obtener una instancia de ObjectQuery que representa una colección de conjuntos de entidades. Normalmente, la clase ObjectContext se utiliza como subclase, bien por parte de una clase generada por las herramientas Entity Framework o bien por las clases POCO, mientras que las propiedades del contexto del objeto devuelven conjuntos de entidades como una ObjectQuery (en .NET Framework versión 3.5 SP1) o como un ObjectSet (en .NET Framework versión 4). La clase ObjectSet extiende la clase ObjectQuery para proporcionar funcionalidad, como agregar y eliminar objetos, en el contexto de un conjunto de entidades con tipo.
La consulta ObjectQuery predeterminada proporciona una consulta inicial que devuelve todas las entidades del tipo especificado. Esta consulta se puede refinar aún más utilizando métodos del generador de consultas o LINQ to Entities.
En el siguiente ejemplo se realiza una consulta en el contexto del objeto para buscar la colección de Products
.
Using context As New AdventureWorksEntities
Dim products As ObjectSet(Of Product) = context.Products
Dim productsQuery = _
From product In products _
Select product
Console.WriteLine("Product Names:")
For Each product In productsQuery
Console.WriteLine(product.Name)
Next
End Using
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<Product> productsQuery = from product in context.Products
select product;
Console.WriteLine("Product Names:");
foreach (var prod in productsQuery)
{
Console.WriteLine(prod.Name);
}
}
Ejecución de la consulta
Una consulta de objeto se ejecuta cuando:
Se enumera mediante una instrucción foreach (C#) o For Each (Visual Basic).
Se enumera mediante una operación de colección tal como ToArray, ToDictionary o ToList.
Al método Execute se le llama explícitamente.
Los operadores LINQ, tal como First o Any, se especifican en la parte más externa de la consulta. Para obtener más información, vea Métodos del Generador de consultas (Entity Framework).
Observe que si como resultado de la ejecución de una consulta no se devolviera nada del origen de datos, los resultados contendrán una colección vacía y no un valor null.
Las consultas ejecutadas por Entity Framework se evalúan con respecto a los datos del origen de datos, y los resultados no se reflejarán con respecto a los objetos nuevos del contexto de objetos. Si ya se ha adjuntado al contexto una entidad con la misma identidad que la que se consulta, los datos procedentes del origen de datos y los datos ya presentes en el contexto se combinan según la opción MergeOption de la consulta. Para obtener los datos que se encuentran en la memoria caché, utilice el método GetObjectStateEntries en la clase ObjectStateManager. ObjectStateManager administra el estado de objetos dentro de un contexto de objetos, de modo que si desea obtener todos los objetos que se agregaron, modificaron y no cambiaron, puede pasar un OR bit a bit de los siguientes valores EntityState al método GetObjectStateEntries: Added, Modified, Unchanged. Para obtener más información vea el blog que muestra cómo realizar consultas locales.
En el siguiente ejemplo, se llama al método Execute para ejecutar una consulta:
Using context As New AdventureWorksEntities()
Dim query As ObjectSet(Of Product) = context.Products
' Execute the query and get the ObjectResult.
Dim queryResult As ObjectResult(Of Product) = query.Execute(MergeOption.AppendOnly)
' Iterate through the collection of Product items.
For Each result As Product In queryResult
Console.WriteLine("{0}", result.Name)
Next
End Using
using (AdventureWorksEntities context =
new AdventureWorksEntities())
{
ObjectSet<Product> query = context.Products;
// Execute the query and get the ObjectResult.
ObjectResult<Product> queryResult = query.Execute(MergeOption.AppendOnly);
// Iterate through the collection of Product items.
foreach (Product result in queryResult)
Console.WriteLine("{0}", result.Name);
}
Proyección de consultas
Las consultas de objeto se utilizan a menudo para devolver datos del modelo conceptual como objetos entidad, pero también pueden devolver un objeto DbDataRecord para los resultados anidados y las proyecciones anónimas, o pueden devolver tipos CLR primitivos para conjuntos de valores únicos.
LINQ to Entities y Entity SQL admiten ambos proyección de consultas. Las consideraciones siguientes se aplican a las proyecciones de consultas:
Algunos métodos de extensión requieren la recopilación de varios resultados como entrada. Si ObjectQuery representa una consulta que devuelve una colección con un único resultado escalar y se llama a uno de estos métodos de extensión, se produce una excepción ArgumentException, como en el siguiente ejemplo.
' Define a query projection that returns ' a collection with a single scalar result. Dim scalarQuery As New ObjectQuery(Of Int32)("100", context) ' Calling an extension method that requires a collection ' will result in an exception. Dim hasValues As Boolean = scalarQuery.Any()
// Define a query projection that returns // a collection with a single scalar result. ObjectQuery<Int32> scalarQuery = new ObjectQuery<Int32>("100", context); // Calling an extension method that requires a collection // will result in an exception. bool hasValues = scalarQuery.Any();
Si ObjectQuery puede devolver un valor null cuando se proyecta a un tipo primitivo, se debe utilizar la versión que acepta valores NULL del tipo. La consulta siguiente utiliza un elemento DateTime que acepta valores NULL porque la propiedad ShipDate del objeto SalesOrderHeader puede devolver un valor null.
Dim shipDateQuery As ObjectQuery(Of Nullable(Of DateTime)) = _ context.SalesOrderHeaders.Where("it.CustomerID = @contactId", _ New ObjectParameter("contactId", contactId)).SelectValue(Of Nullable(Of DateTime))("it.ShipDate")
ObjectQuery<Nullable<DateTime>> shipDateQuery = context.SalesOrderHeaders .Where("it.CustomerID = @contactId", new ObjectParameter("contactId", contactId)) .SelectValue<Nullable<DateTime>>("it.ShipDate");
Para obtener más información, vea Tipos que aceptan valores NULL (Guía de programación de Visual Basic) o Nullable Types (C# Programming Guide).
Ver comandos de almacenamiento
Cuando se consulta un modelo conceptual, Entity Framework transforma la consulta LINQ to Entities y Entity SQL basada en el modelo conceptual en una consulta equivalente que se realiza en el origen de datos. Entity Framework proporciona los métodos System.Data.Objects.ObjectQuery.ToTraceString y System.Data.EntityClient.EntityCommand.ToTraceString, que permiten ver estos comandos de almacenamiento en tiempo de ejecución sin necesidad de realizar un seguimiento en el origen de datos. Para obtener más información, vea Cómo ver los comandos de almacenamiento (Entity Framework).
Recuperar un objeto por su EntityKey
Si conoce el valor de clave de una entidad, puede recuperarlo del origen de datos sin necesidad de crear ni ejecutar explícitamente una consulta de objeto. Los métodos GetObjectByKey y TryGetObjectByKey de ObjectContext devolverán un objeto con la EntityKey especificada en el contexto del objeto. Si usa GetObjectByKey, deberá controlar una ObjectNotFoundException cuando la EntityKey proporcionada no corresponda a ninguna entidad existente. Para obtener más información, vea Cómo: Devolver un objeto concreto usando su clave (Entity Framework).
Vea también
Conceptos
Consultar un modelo conceptual (Entity Framework)
Trabajar con ObjectSet (Entity Framework)
Consultas compiladas (LINQ to Entities)