An even and balanced appraisal of Microsoft Research’s Comega language
Comega is a strongly-typed data oriented language that extends C#, adding support for relational and semi-structured hierarchical data, and it rocks! Imagine C# crossed with SQL and XPath/XQuery with a few constructs for handling concurrent programming thrown in also and you’d have some idea of what Comega is like. The language overview does a great job of giving an overview, so in this fairly ad-hoc article I’m going to attempt to overcome the blurb paradox and show how the new language constructs help bridge the object - relational “impedance mismatch” that so much effort is spent overcoming using today’s tools. I’ll save the equally juicy object – XML bridging for later.
The example that I’m going to discuss is a simplified version of the Comega “Select” tutorial that is installed with Comega and available on-line here. I’m going to show you code samples as screen-shots in the IDE to help illustrate the great job the Comega developers have done integrating it with the Visual Studio 2003 IDE, and hopefully give you an idea of how powerful some of these language constructs might be. I should point out that I am by no means an expert on Comega (or anything else really) and have no academic background in language design. I've just been playing around with this and wanted to share what I have found.
Below we can see our simple Comega program. At a casual glance it looks like a normal C# program, indeed lines 1 – 17 are valid C#, then we get to line 18 and everything we know about crossing the object-relational boundary goes out the window. Lines 18 – 22 contain a statement that looks remarkably like a SQL database query (except that the C# operator for equality “==” is used, rather than the usual SQL “=” operator, and some of those words look like language keywords!). The results of this apparent SQL query are assigned to a variable res (which, interestingly is not declared anywhere)
Next lines 26 – 28 iterate over the row objects in the res object, printing out the Customer ID and Contact Name, which are exposed as members of the row (whatever that is). Running the program produces this output from the long-suffering Northwind database:
The comments above the query tell us that the select expression returns a stream of rows, but what does that mean? Comega streams “represent ordered homogeneous collections of zero or more values”, which are similar to the generic IEnumarble<T> interface coming in .NET Framework 2.0. Each row in the stream (which we iterate over on lines 26-28) is another new type in Comega – an anonymous struct (think “tuple”) that is created at compile time for us.
This compile-time anonymous struct generation allows Comega to do compile time checking when we attempt to access members of the struct, so for example if we altered line 27 to include a property that is not in our “selected” list we get a compiler error (and you thought typed datasets were cool).
Comega’s integration with Visual Studio means it can even give us Intellisense on the members of the anonymous struct.
Comega can also provide us with assistance when we are writing our “select” statement. For example if we include a field that isn’t present in our database (Foo in the example below) we get a compile error.
So how does this magic work? Does Comega query my database at compile time (and if so how, since I haven’t specified how to connect to it, come to think of it how does it connect at run-time?)? No – the answer to this small mystery lies in the Northwind namespace (see the using statement on line 4 of our sample application). The types in the Northwind namespace are generated from our database schema using a tool called Xsd2Comega.exe (installed when you install Comega). Pleasantly this tool (and the equivalent one for generating Comega-friendly types from Xml schema files) has been integrated into VS.NET (as well as being callable from the command line) so when you create a Comega project you can optionally “add a reference” to a database schema or XSD.
Observant readers will also note the .config file shown in the solution explorer screen-shot above – this contains an appSettings config element with the key “Northwind” and a connection string as the value which is used by Comega to connect at run-time. To paraphrase Han Solo selecting against a single table is one thing, to provide joining, grouping, ordering and aggregation capabilities – that’s something else. Fortunately Comega provides a very rich set of SQL-like functionality.
I hope this short and fairly ad-hoc article has sparked your curiosity regarding Comega and maybe (hopefully?) shown you a glimpse of a better world of the near future where object and relational views can live together in the same programming model, and where we can all drive to work in flying cars and take holidays to the moon*.
* Bridging of object relational divide, flying cars, holidays to outer space, world peace and an end to hatred and injustice subject to change without notice. Your mileage may vary. Colours may differ from those shown. May contain traces of nut.