Interacting with databases has never felt all that natural to me. I've tried using several flavors of object-relational-mapping tools, I've tried writing my own mapping objects, and I've tried most flavors in between. And, while most of the accepted approaches had their strengths, they usually left me feeling a bit empty.
For years I've tried to figure out what it was about these techniques that didn't seem quite right. Certainly, many of these approaches were relatively good at performing basic create, read, update, and delete operations. It would also be fair to say that these tools seemed to do a reasonable job of limiting the amount of time I had to invest in writing SQL.
So, why, if these tools were so adequate, did they still leave me wanting more?
I never answered these questions for myself and I'd kind of given up hope and accepted the status quo. Then, when I wasn't really looking for an answer, I found one. For me, it came in the form of Microsoft's Language Integrated Query (LINQ).
With LINQ, which is currently avail-able in beta release, Microsoft seems to be openly acknowledging the fact that building yet another mapping tool would have been pointless. If they were going to make substantive, meaningful strides in the area of querying and accessing data, they had to take a step back and look at how the .NET languages could be enhanced in a way that would promote more natural and dynamic forms of interaction with all types of data.
The example shown in Figure 1 helps highlight what I'm getting at here. The syntax of this sample query, which uses LINQ to find items in a collection, shouldn't be all that foreign. LINQ queries leverage all the fundamental concepts that are part of traditional query languages.
If you've done any SQL at all, the select, from, and where clauses in this query should look very familiar. However, instead of cobbling these elements together into some query string, I am able to construct my expression using built-in language constructs.
LINQ's query syntax isn't earth-shattering, but you have to admit it's quite a leap forward from the days of shipping out SQL strings and praying they wouldn't blow up at run time. It's very comforting to know that each query I write will be treated as a first-class citizen in the .NET run time. In fact, with LINQ, each of these queries will be fully validated at compile time.
I also like the idea that LINQ doesn't force me to learn yet another complex hierarchy of classes to assemble and execute my query. In fact, when I look at LINQ queries, I don't see classes and methods--I see an expression. Overall, I think this dynamic makes LINQ very approachable and intuitive.
LINQ also brings a new perspective to what it means to "query" a data source. In the world of LINQ, a query is not limited to any particular kind of data. LINQ allows queries to be applied universally to any number of different data structures.
With LINQ I can construct queries to execute against in-memory collections, XML (via XLINQ), and relational data-bases (via DLINQ). In fact, you'll notice that the example in Figure 1 is actually performing its query against a list of objects. This built-in ability to create a unified view of data across many domains is one of the most intriguing and powerful aspects of LINQ.
The element of LINQ that really pushed me over the edge, though, was the language's ability to create anonymous types to hold the output of a query (see Figure