I have been looking at the Linq Preview under Reflector, and the more I spend time with it, the more I realize how well thought out and practical it is.
- All queries are lazily executed. When queries are created, a tree of iterators or query objects are constructed. These queries are only processed and only return results when an enumerator is extracted in a foreach loop.
- Queries are also "live" and reusable. If the original data source or collection changes, the results of the queries also change.
- Xml and object implementations are both based completely on iterators. There is no Common Query Runtime involved. The object query extension methods in System.Query.Sequence are all based on iterator methods and IEnumerable<T>. The XML query extension methods are found in System.Xml.XLinq and extend IEnumerable<XElement>. The combination of extension methods, lambda expressions and iterators are powerful to match the full capabilities of XQuery.
- Database queries are processed on the server, except for those operators not expressable in SQL in which case the inexpressable constructs are processed locally. The database query extension methods are found in System.Data.DLinq.QueryExtensions and extend Query<T> (which derives from IEnumerable<T>) with query methods that take distinguished expression trees in place of lambda expressions.
I feel more comfortable with the XML integration today. XElements are a lot more convenient to work with than XmlElements, currently provided by the framework. Construction is simplified through a functional notation.
Selection via XPath strings is not available as far as I can tell, but XElements do provide analogous methods. Instead of element.SelectNodes(“x//z”), one writes element.Elements(“x”).Descendants(“z”). To extract just a single node without unnecessary overhead, one simply calls First() on the result.
XElements are inheritable, so it may be possible to add some semblance of type-checking. I imagine that one can write more compact constructors this way and also add support for object intializers and types accessors this way.