The core piece of Linq is a query language which can query many, many kinds of data. Of course, its the 'many' part which is difficult to get right. The tricky part is that, if you are going to query different kinds data, you have to specify something that all your data types have in common, and then build your query language on top of that commonality. Take SQL & ODBC, which together form a technology that can be used to access many different kinds of data and provide a query language for that data using SQL. Over the years we have seen ODBC drivers that can query SqlServer, DB2, Oracle, and MSAccess. Of course ODBC drivers have provided access to more then just databases, there are ODBC drivers for Excel, text files and a host of other common data sources. What they all have in common is that this data is rectangular: it is made up of rows and columns. This makes sense because ODBC and SQL were designed for database access and databases are traditional stores of rectangular data, which is why using ODBC drivers to access non-rectangular data requires so much duct tape. This is not just about the SOURCE data being rectangular, in SQL the RESULTS are also primarily returned as rectangles. If you were thinking about generating a more general query language which can handle other types of data - like xml - you would need to be able to handle more then just this (not to mention the fact that you would want the creation of new data sources to be much easier then it was in ODBC).For Linq, the commonality between the types of data you can query is that they all need to implement IEnumerable and, more frequently, its generic cousin IEnumerable<> (there is some simplification here for remote data sources, a simplification I hope to return to in a later post, but from a high level this is accurate). Once you start working with Linq for any real length of time, you will start to realise that IEnumerable<> is looking less like 'just another datatype' and more like a first class citizen of the language. Query expressions (i.e. the 'from ... select' syntax for querying in Linq) are designed to work over IEnumerable's as its data sources, and it returns IEnumerable's as the result. Using IEnumerable as your common format is a good choice for a number of reasons, but the ones that impress me are:
Let me give you an example; In DLink you can directly execure your own SQL statements (including stored procedures) by calling the ExecuteQuery method:
IEnumerable<Customer> customers = db.ExecuteQuery<Customer>("exec GetCustomersProc");
This is the general 'escape hatch' for using DLinq without the O/R mapping. The results that come back from this query get converted into Customer objects (one for each returned row) that are exposed through an IEmumerable<Customer> What is nice is that:
It will be interesting to know if in 3 years we don't see people talking about the pervasiveness of IEnumerable similar to how people used to talk about IUnknown. I wait for the first IENMRBL license plate with bated breath...