jsinq.Query

jsinq.Query is where the magic happens, that is where LINQ-style queries are turned into JavaScript code. jsinq.Query depends on jsinq.Enumerable, so make sure you include both files when using the query-expression capabilities of JSINQ.

var query = new jsinq.Query("from customer in $0 where customer.lastname.charAt('0') == 'S' select customer.lastname");

This is how you create a new Query. The Query constructor receives the string that contains the query, leaving you with a Query object that is (almost) ready to use. If there is a syntactical error in your query, the query compiler will catch it and throw a QueryTranslationException. Inspect the exception object to see the error message, line number and character offset at which the error occurred. Note that (for now), the error messages produced by the query compiler are pretty bad and the line number given in the exception object is often nowhere near where the actual error occurred. Also note that the query compiler will catch errors in expressions that may be part of the query, so make sure you check those as well.

A query object essentially is a prepared statement, similar to those you might know from writing database applications. That means that a query object is a query waiting to be executed. Before you can do that however, you have to assign values to all placeholders that may exist in your query. Since queries are specified as strings, they are slightly detached from their surroundings and they cannot access variables from "the outside world". This may seem like a problem, but it really isn't. Where you would normally use variables, you can instead use placeholders. These are composed of a dollar sign and a number (like this: $0) which makes them easy to distinguish from "real" variables. To assign a value to a placeholder, you use the setValue method like so:

var query = new jsinq.Query("from customer in $0 where customer.lastname.charAt('0') == 'S' select customer.lastname");
query.setValue(0, myCustomers);

The nice thing about placeholders is that you can keep assigning different values to them as often as you like. So you can use the same query over and over again but have it work on different datasets, with different constraints and so forth.

After you have assigned values to all placeholders, you call the execute method. The execute method executes the query and returns its result (which generally is an Enumerable):

var query = new jsinq.Query('from customer in $0 where customer.lastname.charAt('0') == 'S' select customer.lastname');
query.setValue(0, myCustomers);
var filterCustomers = query.execute();

And that is all there is to writing queries! If you are new to LINQ and are not familiar with the query expression syntax, check out these examples: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx (note that some of these are a little outdated and the syntax has since changed a little).

Spanning queries across multiple lines

The most common way of formatting a LINQ query is to put each clause on its own line like this:

from c in customers
join o in orders on c.id equals o.customerId
where o.items > 10
orderby c.lastname
select {lastname: c.lastname, items: o.items} 

Unfortunately, JavaScript does not natively support multi-line strings. So you're stuck with writing something like this:

var query = "from c in customers" +
    "join o in orders on c.id equals o.customerId" +
    "where o.items > 10" +
    "orderby c.lastname" +
    "select {lastname: c.lastname, items: o.items}",

Unless you are willing to let language specifications be language specifications and exploit a bug/feature found in pretty much all JavaScript implementations:

var query = "from c in customers \
    join o in orders on c.id equals o.customerId \
    where o.items > 10 \
    orderby c.lastname \
    select {lastname: c.lastname, items: o.items}",

Yes, it's still ugly, but less so. Note that there cannot be any whitespace after the backslash at the end of each line. If you choose to use this "feature", make sure you thoroughly test your application in all browsers that you are targeting.

Methods

jsinq.Query provides the following methods:

Method Static Description
setValue no Binds a specified value to a placeholder
execute no Executes the query and returns the result
getQueryFunction no Returns the anonymous function that executes the query

Last edited Mar 27, 2010 at 2:16 PM by kaijaeger, version 2

Comments

No comments yet.