Skip to content

Queries

Nathan Baulch edited this page Jun 16, 2014 · 1 revision

LINQ provides an intuitive, statically typed means of querying resources without needing to understand the underlying SData URL components, particularly the filter expression language.

Note: LINQ was introduced in .NET 3.5 so the .NET 2.0 version of this library doesn't support LINQ queries.

Queries automatically handle paging, so a single query might span multiple requests. The following example requests a list of active contacts ordered by last name then first name with addresses included.

var client = new SDataClient("http://example.com/sdata/slx/dynamic/-/")
    {
        UserName = "admin",
        Password = "password"
    };
var contacts = await client.Query<Contact>()
    .Where(c => c.Status == "Active")
    .OrderBy(c => c.LastName)
    .ThenBy(c => c.FirstName)
    .Fetch(c => c.Address)
    .ToListAsync();

[SDataPath("contacts")]
public class Contact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Status { get; set; }
    public Address Address { get; set; }
}

The SDataPath attribute on the contact POCO specifies the path of the resource relative to the base URL of the client object. Without this attribute the resource path would need to be specified every time a query is created.

Projections

Selecting only the required properties is a good way to reduce the amount of data fetched from the server. This is accomplished using the standard Select operator. The LINQ provider finds all referenced properties in the projection lambda expression and builds a minimal SData select argument. The following example performs the same contact query as above but selects a subset of the available properties into an anonymous type.

var contacts = await client.Query<Contact>()
    .Where(c => c.Status == "Active")
    .OrderBy(c => c.LastName)
    .ThenBy(c => c.FirstName)
    .Select(c => new {c.LastName, c.FirstName, c.Address.City, c.Address.State})
    .ToListAsync();

In addition to the contact name properties, two address properties are also pulled into the result object. The additive Fetch operator has been removed because the subtractive Select operator takes precedence. There is currently no way to limit the selected properties without changing the resource type, which means the query returns anonymously typed objects that cannot be updated.

Operators

The following standard LINQ operators are supported.

Grouping, joining, aggregation and set based operations are not supported due to SData protocol limitations. These operations can still be used in-memory once the query is materialized using ToList or ToArray, however it's important to understand the data transfer implications when doing so.

In addition to the standard operators, the following extension operators are available:

  • Fetch: Specify related resources and collections that should be included in the results.
  • WithPrecedence: Set the payload control precedence threshold. Setting this to zero is a convenient way to request empty resources with only protocol properties such as $key present.
  • WithExtensionArg: Append underscore prefixed extension arguments to the query string of the generated URL.

Filter Methods

The following methods are supported in filter predicates. They are mapped to standard SData functions that are evaluated on the server side.

The following extension methods are available in addition to the ones above.

  • Ascii
  • Between
  • Char
  • In
  • Left
  • Like
  • Right

Refer to section 2.12 of the SData specification for definitions and usage examples.

Untyped Queries

The LINQ provider also recognizes string indexer properties, making untyped queries on SDataResource possible. A path should be provided when using this approach since it cannot be automatically determined the usual way via the SDataPath attribute. The following example performs the same contact query as above but without the need for a contact POCO.

var contacts = await client.Query("contacts")
    .Where(c => c["Status"] == "Active")
    .OrderBy(c => c["LastName"])
    .ThenBy(c => c["FirstName"])
    .Fetch(c => c["Address"])
    .ToListAsync();

Non-LINQ Queries

When using the .NET 2.0 version of this library query requests must be built manually. The following example makes the same contact query used above but using the Execute method directly.

var param = new SDataParameters
    {
        Where = "Status eq 'Active'",
        OrderBy = "LastName,FirstName",
        Include = "Address"
    };
var results = await client.ExecuteAsync<IList<Contact>>(param);
var contacts = results.Content;

This approach doesn't automatically handle paging the way LINQ queries do.

More information on queries can be found in section 6 of the SData specification.

Clone this wiki locally