Types of Queries Against OpenAccessContext

This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.

A query is an expression that retrieves data from a data source. Queries are usually expressed in a specialized query language. Therefore, developers have had to learn a new query language for each type of data source or data format that they query. Language-Integrated Query (LINQ) offers a simpler, consistent model for working with data across various kinds of data sources and formats. In a LINQ query, you always work with programming objects.

A LINQ query operation consists of three actions: obtain the data source or sources, create the query, and execute the query.

Data sources that implement the IEnumerable generic interface or the IQueryable generic interface can be queried through LINQ.

In the query, you specify exactly the information that you want to retrieve from the data source. A query can also specify how that information should be sorted, grouped, and shaped before it is returned. In LINQ, a query is stored in a variable. If the query returns a sequence of values, the query variable itself must be a queryable type. This query variable takes no action and returns no data; it only stores the query information. After you have created a query, you must execute that query to retrieve any data.

In a query that returns a sequence of values, the query variable itself never holds the query results and only stores the query commands. The execution of the query is deferred until the query variable is iterated over in a foreach loop.

In contrast to deferred queries, which return a sequence of values, queries that return a singleton value are executed immediately. Some examples of singleton queries are Count, Max, Average and First. These execute immediately because the query results are required in order to calculate the singleton result. You can also use the ToList or ToArray methods on a query to force immediate execution of a query that does not produce a singleton value.

Query Expression Syntax

Query expressions are a declarative query syntax. This syntax enables a developer to write queries in a high-level language that is formatted similar to Transact-SQL. By using query expression syntax, you can perform even complex filtering, ordering, and grouping operations on data sources with minimal code.

The following example uses Select to return all the rows from Products and to display the product names.

using ( EntitiesModel dbContext = new EntitiesModel() )
{
   IQueryable<string> productNames = from product in dbContext.Products
                                     select product.ProductName;
   Console.WriteLine( "Product Names:" );
   foreach ( string productName in productNames )
   {
       Console.WriteLine( productName );
   }
}
Using dbContext As New EntitiesModel()
 Dim productNames As IQueryable(Of String) = From product In dbContext.Products
                                             Select product.ProductName
 Console.WriteLine("Product Names:")
 For Each productName As String In productNames
  Console.WriteLine(productName)
 Next productName
End Using

Method-Based Query Syntax

Another way to compose LINQ queries is by using method-based queries. The method-based query syntax is a sequence of direct method calls to LINQ operator methods, passing lambda expressions as parameters.

This example uses Select to return all the rows from Products and to display the product names.

using ( EntitiesModel dbContext = new EntitiesModel() )
{
   IQueryable<string> productNames = dbContext.Products.Select( p => p );
   Console.WriteLine( "Product Names:" );
   foreach ( string productName in productNames )
   {
       Console.WriteLine( productName );
   }
}
Using dbContext As New EntitiesModel()
 Dim productNames As IQueryable(Of String) = dbContext.Products.Select(Function(p) p)
 Console.WriteLine("Product Names:")
 For Each productName As String In productNames
  Console.WriteLine(productName)
 Next productName
End Using

Composing Queries

As mentioned earlier in this topic, the query variable itself only stores the query commands when the query is designed to return a sequence of values. If the query does not contain a method that will cause immediate execution, the actual execution of the query is deferred until you iterate over the query variable. Deferred execution enables multiple queries to be combined or a query to be extended. When a query is extended, it is modified to include the new operations, and the eventual execution will reflect the changes. In the following example, the first query returns all the products. The second query extends the first by using Where to return all the products with unit price > 20.0:

using ( EntitiesModel dbContext = new EntitiesModel() )
{
   IQueryable<Product> products = dbContext.Products.Select( p => p );
   IQueryable<Product> expensiveProducts = products.Where( p => p.UnitPrice > 20 );
   Console.WriteLine( "Product Names:" );
   foreach ( Product product in expensiveProducts )
   {
       Console.WriteLine( product.ProductName );
   }
}
Using dbContext As New EntitiesModel()
 Dim products As IQueryable(Of Product) = dbContext.Products.Select(Function(p) p)
 Dim expensiveProducts As IQueryable(Of Product) = products.Where(Function(p) p.UnitPrice > 20)
 Console.WriteLine("Product Names:")
 For Each _product As Product In expensiveProducts
  Console.WriteLine(_product.ProductName)
 Next _product
End Using

See Also