Query Expressions

From RemObjects Software

Jump to: navigation, search

This is a Oxygene Language Feature topic
Feel free to add your notes to this topic below.


Based upon the sequence type introduced in 'Joyride', Oxygene provides a powerful syntax for working on sequences in a syntax similar to SQL. Query Expressions enable you to perform actions such as filtering, sorting, partitioning and joining of data in sequences in an intuitive way, and providing full compile-time type checking and Intellisense.

Much like sequences themselves, Query Expressions can be backed by in-memory data or information from remote sources. Actions performed through query statements might be either performed locally on in memory data, or be processed on the data back-end before data is actually transferred.

For example, sorting a sequence using the "order by" clause will work seamlessly, for an "array of String" or for a database table containing millions of records. In the case of the array, the sorting will happen on the local system, but for the data table, the back-end SQL database can handle the sorting as part of the data retrieval. The same concepts would apply to filtering ("where" clause) and other operations.

Oxygene's Query Expressions are largely based on the Standard Query Operators introduced by the Microsoft .NET Framework 3.5 and the types defined in the "System.Query" namespace. However, Oxygene's implementation of the language feature is only loosely coupled to these classes, and can work with class libraries that follow the same principles. The necessary details about this for library implementers go beyond the scope of this topic, but are covered in the Oxygene documentation.

Query expressions use a syntax that is similar to the Structured Query Language (SQL) commonly used in database systems. Even though there are slight differences, this will make query expressions easy and intuitive to use for developers familiar with database development. The query expression syntax is also easy and simple enough to make it accessible to new developers, as it avoids many of the complexities and ambiguities of its distant cousin SQL.

In Oxygene, all query expressions work on sequences and select types that provide explicit compatibility with query expressions (such as the DLinq data table classes). The result of a query expression will also be a sequence (or a compatible type, respectively). For the purpose of this topic, we will concentrate on working with Oxygene sequence types exclusively.

A query expression is started with a "from" clause, and can be followed by zero or more additional clauses that act on the sequence. The simplest imaginable query expression would be along the lines of:

var x := from c in MyCustomers;

where MyCustomers would be an existing sequence of customer objects, and this query expression does nothing more then returning exactly that same sequence - a no-op, in other words.

For query expressions to be sensible, we would of course want them to perform some actual operations on the data, but before we look at some examples, let us define a couple of classes that we will use throughout the rest of this topic:

type
  Customer = public class
    property Name: String;
    property Street: String;
    property City: String;
    property Country: String;
    property DateOfBirth: DateTime;
    property Orders: sequence of Order;
  end;

  Order = public class
    property OrderID: String;
    property OrderDate: DateTime;
    property Total: Double;
  end;

var
  MyCustomers: sequence of Customers := ... // fill this list, somehow

These classes, and the MyCustomers variable can now help us illustrate the various operations we can perform using query expressions.

Query Operators

The simplest query you have seen above will do nothing more than directly assign MyCustomers to the x variable. a number of Query Operators are provided to extend a from clause and perform operations such as filtering, grouping or sorting on the sequences.

These operators are implemented by calling a set of Query Operators defined by the .NET 3.5 runtime.

for each/Query Shortcut Syntax

Oxygene introduces a combined syntax for for each loops and queries. Using the plain old for each syntax, one could write the following, where everything inbetween in and do is a standard query expression:

for each c1 in from c2 in Customers where c2.Age > 30 do
  ...

This looks odd and stilted, as there are two loop variables (c1 for the actual for loop, and c2 for the query). This seems redundant – and indeed it is.

In Oxygene, this can now be shortened to the more concise and more intuitive

for each from c in Customers where c.Age > 30 do
  ...

Here, c acts as both the variable for the Query, but will also become the loop variable. More precisely, it's the final element of the query that will become the loop variable. Consider this more complex example, where n will be the variable in the for loop, which will iterate over all strings:

for each from c in Customers where c.Age > 30 select c.FirstName+' '+c.LastName into n do
  ...


See Also


Product: RemObjects Oxygene (formerly known as Chrome)
Current version: 3.0 Previous Versions: 'Joyride' (2.0), 'Floorshow' (1.5), 'Adrenochrome' (1.0)

GlossaryKeywordsLanguage FeaturesPlatform FeaturesSamplesArticlesHow ToIssues

Personal tools