We have implemented a LINQ provider for Siaqodb. LINQ is the default and the only (public for client code) query engine available. What does the LINQ provider really mean for Siaqodb and why is it important to know how it works for Siaqodb?

In general a LINQ provider translates LINQ queries into specific API calls against a data source. It enables you to write LINQ queries in C#, and have those queries executed based on the native language of the data source. LINQ for Siaqodb translate a lambda expression passed in to an internal query and based on that query, data is pulled from the database and provided to the client code. There are two main techniques to implement a LINQ provider:

  1. Implementing the IQueryable interface
  2. By re-defining IEnumerable LINQ extension methods for a custom interface that inherits from IEnumerable

We use the second technique and currently Siaqodb LINQ provider can optimize the following LINQ operations by re-defining new methods for:

Any(…)
Count(…)
First(…)
FirstOrDefault(…)
Join(…)
Last(…)
LastOrDefault(…)
Select(…)
Single(…)
SingleOrDefault(…)
Take(…)
Skip(…)
Where(…)

Not all LINQ queries may be optimized by Siaqodb. Take a look at UnOptimizedExamples.cs file in our Examples project. For these cases it falls back to LINQ to Objects. This is the advantage of the second technique we use, rather than implementing the IQueryable interface.

Let’s take a closer look at a few LINQ extension methods:

1.Where(…)

When you do a query like:

var q=from Person p in siaqodb
where p.Age=30
select p;

This query gets transformed into an internal Where object. The engine looks up if Age is an indexed field, if so, it takes all the OIDs for the key with value 30, it builds the objects associated to these OIDs, hydrates them and returns them to the caller. If the Age field is not indexed, the query is still optimized by fetching ONLY the Age field for each object in order to determine which objects have an age of 30. Only matching objects are created, hydrated and returned to the caller.

2.Select(…)

Siaqodb is able to return complete or partial objects from the database:

var q=from Person p in siaqodb
select p;

In this example Siaqodb will load complete Person objects from the database. However, the following query:

var q=from Person p in siaqodb
select new {Name=p.Name};

will only load the values for the property/field Name from the database. This style of queries are significantly faster than the alternative of first returning a complete Person object and afterwards extracting the Name value.

3.Pagination: Skip/Take

The Skip and Take methods can be used to extract batches of records from the database. This enables pagination optimizations by not displaying the whole data set:

var query = (from Developer emp in siaqodb
where emp.Age>20
select emp).Skip(10).Take(10);

In this example the first 10 objects are skipped and only the next 10 objects are instantiated and returned.