C-Omega Overview
Reposted from 9CBS, author dotnet_editor ---------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------- Dare ObasanJomicrosoft Corporation
Summary: Dare Obasanjo introduces the C-Omega programming language. This language is created by Microsoft Research, and the method is to increase the C # structure so that information such as XML and relational data can be better dealt.
Introduction The XML heterogenese has become a general language for information exchange. One major reason is that it is different from the previous data exchange format, and XML can easily represent strict structured table data (relational data or serialized objects) and semi-structured data. Office documentation). The former is often stronger type data, usually treated with Object <-> XML mapping technology, and the latter is often non-type data, typically using conventional XML technology (such as DOM, SAX, and XSLT). However, in both cases, developers feel some out of stam when using traditional object-oriented programming languages.
In the case of using Object <-> XML mapping technology, the programming language object is "impedance mismatch" between the programming language object and the XML schema language (such as DTD or W3C XML architecture). The difference model, document order, and content model selected between element and attributes, etc. All of these concepts are of the XML schema language itself, but there is no corresponding concept in traditional object-oriented programming. These mismatched aspects often cause certain distortions and data loss when the XML is mapped to an object. There are some different problems when using techniques such as XSLT or DOM to handle non-type XML documents. In the case of a specific language (such as XQuery) using XSLT or other XML, developers must systematically learn another language to effectively process XML and their selected programming languages. Typically, all the benefits of the primary language integration development environment (such as compile time checking and intelligent perception) cannot be utilized when processing XML. In the case of processing XML with an API (such as DOM or SAX), developers often complain that the code they must write tend to use it.
When designing modes and application programming interfaces (APIs) for performing specific tasks, they are sometimes fused into programming languages. Similar to C # programming languages have enhanced concepts in other languages as design patterns and API calls, such as this string type, using garbage recycling memory management, and event processing for core constructions in this language. This evolution process has begun to involve XML. When XML becomes more popular, some groups have begun integrating construction and operation of XML constructs into mainstream programming languages. They expect XML to handle local parts of these programming languages, and some of the issues that use traditional XML process technology will become simple. There are two most worthless examples of XML into traditional programming languages, one is c-omga (c-omga) created by Microsoft Research, which is an extension of C #; one is ECMAScript for XML created by Ecma International ( E4X), it is an extension of ECMAScript. This article will outline the XML function of C-Omega, and subsequent articles will explore the E4X language. This article first discusses changes to the C # type system in C-Omega, and then introduces the addition to the C # language to make it easier to handle the relational data and an operator of XML data.
The purpose of the C-Omega Type System C-Omega Type System is to create a gap between the relational data, object data, and XML data access by creating a type system of all three data models. The method supported by the C-Omega type system is not to add a built-in XML or relationship type to the C # language, but add some universal changes to the C # type system, making it more conducive to structured relationship data and half structure. The XML data is programmed.
Many changes to C # in C-Omega make it more conducive to programming strong type XML (especially XML using W3C XML architectural constraints). Some concepts in the XML and XML architecture have similar features in C-Omega. There are some concepts in C-Omega, such as document order, elements, and attributes (including multiple fields, which have the same name but have different values), and the content model selected for a particular field specified type selection. Many of these concepts are processed with traditional Object <-> XML mapping technology, but this often brings a lot of trouble. C-Omega is intended to make strong type XML programming as simple and natural as the array or string in traditional programming languages.
The stream in C-Omega is similar to XQuery and XPath 2.0 and system.collections.Generic.ienumerable type
Declaring streams by adding the operator "*" to the type name of the variable declaration. It is usually used to generate streams using iterative program functions. The iterative program function is a routing sequence of a return value (by using the Yield statement to returns each value) function. When the value is generated, the state of the iterative program function is maintained and the caller is allowed. When the iteration program is called, it will continue to generate the next value from the last state. The iterative program function in C-Omega is similar to the iterative program function for the C # 2.0 program. The most obvious difference between iterative program functions and C # in C-Omega is that the C-Omega iteration program returns stream (T *), while the C # 2.0 iterative program returns an enumerator (IEnumerator). However, when interacting with streams or enumeors, they have some subtle differences in behavior. More importantly, just like the sequences in XQuery, the streams in c-omega cannot contain other streams. Conversely, when multiple streams are combined, the result is compressed into single-first-class. For example, a stream (4, 5) is added to the stream (1, 2, 3), which produces a stream containing 5 items (1, 2, 3, 4, 5), rather than 4 streams (1, 2) , 3, (4, 5)). Although an enumerator of an enumerator can be created in C # 2.0, it is not possible to combine multiple enumerators in such a way. The following iterative program function returns a stream that contains three books in the Lord of The Rings.
Public String * Lotr () {
Yield Return "The Fellowship of the Ring"; Yield Return "The Two Towers"; Yield Return "The Return Of The King";
}
The result of the above function can be handled using a conventional C # foreach loop (shown below).
Public void printtrilogytitles () {
FOREACH (String Title in Lotr ()) Console.writeline (Title);
The powerful function of the C-Omega stream is that the method can be called in the stream, and then convert it into the subsequent method call for each of the streams. The following method shows an example of this function being used:
Public void printtrilogytitLelength () {
Foreach (int size in lotr (). Length) console.writeline (size);}
The above method call will cause the value of the Length attribute to be called each string that is returned by the PrinttrilogyTitles () method. The ability to access stream content attributes in such a polymerization allows the query of the XPath style by the object graphics.
There is also a concept that is applied to all expressions, which makes it possible to apply an anonymous method to each member of the stream. These anonymous methods may contain special variable IT, which is bound to each continuous element of the iterative stream. Below is an alternative implementation of the PRINTTRILOGYTITLES () method (using it is applied to all expressions).
Public void printtrilogytitles () {lotr (). {console.writeLine (it)};
Select Types and Types of Types of Null Values C-Omega's Selection Types Very similar to the federated type in C and C programming languages, '|' operators in DTD, and XS: Choice elements in the W3C XML architecture. Below is an example of a class using the selected type:
Public class newsitem {
String Title; String Author; kice {string pubdate; string body;} In this example, the NewSitem class instance can have the system.string type Pubdate field, or there can be the system.datetime type DATE field, But both cannot exist at the same time. It should be noted that each field of the C-Omega compiler enforces the selection type has different names, otherwise the predetermined type will have an amphony when accessing this field. The method of accessing the Select Type field in C-Omega is different from the federated type in C and C . In C / C , programmers must know what type of value in a particularly federal type is indicated because the compiler does not perform a static type check. However, the compiler is static to check the federal type of C-Omega, which makes it possible to declare them:
Choice {string; datetime;} x = DATETIME.NOW; Choice {string; DateTime;} y = "12/12/2004";
However, there will be a problem, that is how the static statement may depend on the type of field that does not exist in the selection type. For example, in the above example, if the variable is initialized with the instance of System.DateTime, X.Length is not a valid attribute access, while when the string "12/12/2004" is initialized, 10 will be returned. This is the land that can be used for null value.
In the W3C XML architecture and relational database domain, all types can have an instance of NULL. Existing versions of some languages (such as Java) and C # do not allow NULL to assign a value to an integer or floating point. However, when using XML or relational data, it is important to declare a null is very important. In these cases, unwanted attributes of the value can cause nullReferenceExceptions. This problem can be solved for a null value by mapping all values returned by the attribute access to a null value. Here are examples of some types of uses that can be null.
String? s = null; int? size = s.ley; // returns null instead of throwing // nullreferenceException if (size == null) Console.WriteLine ("The value of size is null);
choice {string; DateTime;} pubdate = DateTime.Now;? int dateLen = pubdate.Length; // works since it returns null because // Length is a property of System.String int dateLen2 = (int) pubdate.Length; / / throws nullreferenceException
This function is similar (but different) can be a type of null value in C # 2.0. C # 2.0 The type of null value is a NULLABLE example, which contains a value and an indication (regardless of whether the value is null). In essence, this is a package of some value types (such as integer and floating point types that cannot be NULL). C-Omega takes a further measure when the access value is a field or attribute of null, and returns NULL instead of trigger NullReferenceException. Anonymous structure The anonymous structure is similar to the XS: Sequence element in the W3C XML architecture. The anonymous structure enables certain concepts in the C-Omega-centric concept (such as document order and one element may have multiple names, but different). Anonymous structure is similar to the conventional structure in C #, but there are several critical differences:
1. Anonymous structure has no explicit type name. 2. The fields in anonymous structure are sorted, which allows them to access them through array index operators. 3. The fields in the anonymous structure don't have to be named. They can only have type. 4. Anonymous structure can include multiple fields with the same name. In this case, access these fields will result in a return stream by name. 5. An anonymous structure (i.e., the same member type in the same order) is compatible, and the variable of this structure can be retrofitted.
The following example highlights a variety of features of the anonymous structure in C-Omega.
Struct {int; string; string; datetime date; string;} x = new {47, "Hello World", "Dare Obasanjo", Date = DATETIME.NOW, "this is my first story"}; console.writeline (x [1]); datetime pubdate = x.date;
Struct {long; string; string; datetime date; string;} newsitem = x; console.writeline (newsitem [1] "by" newsitem [2] " newsitem.date); struct {string field; String field; string field;} field3 = new {field = "one", field = "two", field = "three"};
String * strfield = field3.field; // string strfield = field3.field Doesn't Work Since Field3.field Returns A Stream
Struct {int value; string value;} tricky = new {value = 10, value = "ten"}; choice {int; string;} * value = tricky.value;
The content class content class is a class that uses the struct key to group its members to group different units. To some extent, the content class is similar to DTD in XML. Consider the content classes of the Books object: public class books {structure {string title; string author; string public publisher; string? Onloan;
}
This example is similar to the DTD below:
And the following XML architecture:
The following code example shows how to use the books object:
Using Microsoft.comEga; Using System;
Public Class Books {structure {string title; string author; string publisher; string? Onloan;} * book;
Public static void main () {
Books books = new books ();
Books.book = new struct {title = "essential.net", author = "don box", Publisher = "addison-wesley", online = (string?) null}; console.writeline (String) books.book. Author "is the author of" (string) books.book.title;}}
The query operator in C-Omega C-Omega adds two major class query operators to the C # language:
• XPATH-based operators used to query the member variable of the object according to the name or type. • SQL-based operators for performing complex queries including projections, packets, and coupling including one or more object data.
The XPath-based operator has a stream and the presence of an anonymous structure of multiple members of the same name, even if the common direct member access to the "." Operator in c-omga can also be considered a query operation. For example, the previous part of the book.book.title operation will return the title of all Book objects included in the books class. This is equivalent to XPath query '/ books / book / title', which returns all the titles that contain Book elements in the boxs element.
Wildcard Members Access Operators ". *" Can be used to retrieve a type of all fields. This operator is equivalent to XPath Query Child :: *, which returns all child nodes of the primary node type of the current node. For example, operate Books.book. * Returns a flow container, all members of all Book objects are included in the books class. This is equivalent to XPath query '/ books / book / *', which returns all child elements of the BOOK element included in the Books element.
C-Omega also supports access to the "..." operator, which is similar to the Descendent-OR-SELF axis or "//" abbreviated path in XPath. Operation Books ... Title returns a stream in a recursive manner, which contains all Title member fields included in the Books class (or member fields thereof). This is equivalent to XPath query '/ books // title', which returns all Title elements (they are the child of Books elements). It is also possible to use the syntax that can be transmitted to the form of a hand-transmitted operator to limit the syntax in the form of '... typeename :: *' to a particular type of node. For example, operations Books ... string :: * Returns a stream in a recursive manner, which contains all member fields of the System.String type included in the Books class (or member fields thereof). This is similar to XPath 2.0 query / books // element (*, xs: string), which matches any child of the XS: String type BOOKS element.
The screening operation can be applied to the same manner to pass the result, the predicate can be used to filter XPath queries. As in XPath, you can use the '[expression]' operator placed after the query to apply the C-Omega filter to the query operation. As applied to all expressions, the filter can include special variable IT, which is bound to each continuous element of the iterative stream. Below is an example, it queries all the fields of the System.InT32 type in anonymous structure, and then filter the result of greater than 8.
Struct {Int a; int b; int C;} z = new {a = 5, b = 10, c = 15}; int * value = z ... int :: * [IT> 8]; Foreach (int I in value) {console.writeLine (i "is greater ten");
SQL-based operator C-Omega includes many configurations in the SQL language and uses them as a keyword. A operator selected by projection, screening, sorting, packet, and coupling in C-Omega is built. SQL operators can be applied to objects in memory, or it can be applied to relational storage, which can be accessed using ADO.NET. When applied to a relational database, the C-Omega query operator can be converted to SQL query by basic storage. The main advantage of using the SQL operator in the C-Omega language is that query syntax and results can check when compiling instead of runtime check, can also use traditional relationship API to embed SQL expression in a string.
To connect to the SQL database with C-Omega, it must be published as a managed assembly (ie .NET library file), then it can be referenced by the application. Using the SQL2Comega.exe command line tool or the Add Database Schema ... dialog box in Visual Studio in Visual Studio, you can disclose the relational database to C-Omega as a managed assembly. C-Omega uses the Database object to represent the relational database by the server host. The Database object has a common property for each table or view in the database and a method for each table value function in the database. To query the relational database, you must specify a table, view, or table value function as an input of one or more SQL-based operators.
The following sample programs and outputs show some of the features of the SQL-based operator query relational database in C-Omega. The database used in this example is the Northwind database example included with Microsoft SQL Server. The name DB used in the example DB references the northwind.dll assembly (using SQL2Comega.exe generated)'s northwind namespace's global instance of the Database object.
Using system.data.sqltypes; using northwind;
Class test {static void main () {
// The foreach statement can infer the type of the // iteration variable 'row' statically evaluating // the result type of the select expression foreach (row in select ContactName from DB.Customers) {Console.WriteLine ( "{0}" , row.contactname);}}}
The following sample programs and outputs show some of the features of the SQL-based operator query memory in C-Omega.
Code Sampleusing Microsoft.comEGA; Using System;
Public class test {
ENUM CDStyle {Alt, Classic, Hiphop}
Static struct {string title; string artist; cdstyle style; int year;} * cds = new {new {title = "lucky frog", artist = "holly holt", style = cdstyle.alt, year = 2001}, new { Title = "kamikaze", artist = "twista", style = cdstyle.hiphop, year = 2004}, new {title = "stop light green", artist = "robert o'HARA", style = cdstyle.alt, year = 1981}, new {title = "noctures", artist = "chopin", style = cdstyle.classic, year = 1892}, new {title = "mimosa!", Artist = "broth", style = cdstyle.alt, Year = 1980}, new {title = "beg for mercy", artist = "g-unit", style = cdstyle.hiphop, year = 2003}}; public static void main () {
struct {string Title; string Artist;} * results; Console.WriteLine ( "QUERY # 1: select Title, Artist from CDs where Style == CDStyle.HipHop"); results = select Title, Artist from CDs where Style == CDStyle {Console.Writeline ("Title = {0}, Artist = {1}", it.title, it.artist);
Console.writeLine ();
Struct {string title; string artist; int year;} * results2;
Console.writeline ("Query # 2: SELECT TITLE, ARTIST, YEAR from CDS Order By Year"); Results2 = SELECT TITLE, Artist, Year from CDS Order by Year; Results2. {Console.Writeline ("Title = {0} Artist = {1}, iTIAR = {2} ", it.title, it.artist, it.year;};}} OutputQuery # 1: select title , Artist = twistatitle = beg for mercy, artist = g-unit
QUERY # 2: select Title, Artist, Year from CDs order by YearTitle = Noctures, Artist = Chopin, Year = 1892Title = Mimosa !, Artist = Brian Groth, Year = 1980Title = Stop Light Green, Artist = Robert O'Hara, Year = 1981Title = Lucky Frog, Artist = Holly Holt, Year = 2001title = Beg for mercy, artist = g-unit, year = 2003title = kamikaze, artist = twista, year = 2004 in C-Omega, many need to lengthy nested cycles Operations can be simply processed using a declarative operator similar to SQL. The main category of the SQL operator contained in C-Omega is briefly described below.
Projection Selecting Expression is a list of expressions that keep up with SELECT keywords. Each row specified by the FROM clause performs a projection. The role of projection is to configure the result data line to contain only the required columns. The simplest form of the selection command is composed of four parts, a select keyword; after the back is one or more projected expression list, used for the column of the source; followed by a "key; then an expression, then use Source of identifying the query. Here is an example:
Rows = SELECT ContactName, Phone from Db.customers; Foreach (Row In Rows) {Console.Writeline ("{0}", row.contactname);}
In this example, there is no type indicator that specifies the result of the selected query. The C-Omega compiler can automatically infer the correct type. The actual type of a single result line is the C-Omega Tuple type. You can specify the result type directly using the TUPLE type (ie anonymous structure) and an asterisk (*) to specify the result stream. E.g:
Struct {sqlstring contactname;} * rows = select contactname from db.customers;
Struct {sqlstring contactname; sqlstring phone;} * rows = select contactname, Phone from db.customers;
Screening You can use three keywords - one of DistINCT, TOP, and WHERE - to filter the results of the selection expression. The DistINCT keyword is used to limit the result line only there is a unique value. Top keywords are used to limit the total number of queries generated. The TOP keyword is behind a constant expression that specifies the number of rows returned. You can also create a Distinct TOP selection that limits the total number of unique rows returned by the query. The WHERE clause is used to specify the Boolean expression used to filter the rows returned by the query source. Right reserved the value of the value of true, and discard the remaining rows. The following example shows all three screening operators that are being used:
Select Distinct Top 10 ContactName from db.customers where city == "london";
Sort can be classified using the ORDER BY clause to classify the result lines of the selected expression. The ORDER BY clause always selects the last clause of the expression (if fully specified). The ORDER BY clause consists of two parts, two keyword order by; followed by a comma-separated expression list, which defines the value of the determination order. The first expression in the list defines a sorting standard with the highest priority. It may also be necessary to specify that each expression should be sorted in ascending or descending order. All expressions are sorted by ascending order. The following example shows the Order By clause that is being used: Rows = Select ContactName, Phone from Db.customers Order by ContactName Desc, Phone ASC;
The group can be aggregated across multiple lines using Group By clauses and built-in aggregate functions. The Group By clause makes it possible to specify the actual relationship of different lines, which can be combined together. Then, the aggregate function can be applied to each column to calculate the value of the entire group. The aggregate function is a function of calculating single values according to a series of inputs; for example, calculates the sum of many sums or averages. 6 polymeric functions were built in C-Omega. They are Count, Min, Max, AVG, SUM, and STDDDEV. To use these functions in the query, you must first import System.Query namespaces. The following example shows how to use the Group By clause and the built-in aggregate function.
Rows = SELECT Country, Country from DB.CUSTOMERS GROUP BY Country
This example uses the aggregation function to generate a collection of all countries and the number of customers in each country. COUNT () total number of items in groups.
Aggregation can be used in all clauses obtained after the Group By clause. Even if you have specified in the query, you must see the projection list after the Group By clause. The consequences of doing this are unable to apply the aggregate function to the WHERE clause. However, the Having clause can be used to screen the outgictive row. The role of the Having clause is the same as where clauses, and the only difference is that it is calculated after the Group By clause. The following example shows how to use the HAVING clause.
Rows = SELECT Country, Country from DB.CUSTOMERS Group by Country Having Count> 1;
The join selection query can be used to combine the results from multiple tables. The SQL join is a Cartesian product of one or more tables, and each line of one table is paired with each line of another table. All Cartesian product consists of all such pairs. To select multiple sources that should join their data to perform queries, the from clause can actually contain a list of source expressions separated by commas, each of which has its own iterative alias. The following example pairs all Customer rows with their corresponding Order rows, and generate a table, list the delivery date of the customer's name and order.
Rows = select c.contactname, O.ShippedDate from c in db.customers, o in db.orders where c.customerid == o.customerid;
C-Omega also uses the corresponding keyword to support more complex table joint syntax from the SQL field, including Inner Join, Left Join, Right Join, and Outer Join. The grammatical description of various coupled can be found in W3Schools Tutorial on SQL Join. The following example shows the selection expressions using the Inner Join keyword.
Rows = Select C.ContactName, O.ShippedDate from c in db.customers inner Join O in db.orders on c.customerid == O.CUSTOMERID; Data Modifying C-Omega's relational data access capabilities is not limited to query data. You can also use the insert command to insert a new line into the table, modify the existing line in the table with the Update command, or remove the row from the table with the delete command.
The INSERT command is an expression that is calculated successfully inserted into the table due to the execution of this command. The following example plugs the new customer into the Customer table.
INT n = INSERT Customerid = "Abcde", contactname = "frank", CompanyName = "acme" INTO DB.CUSTOMERS;
Use an anonymous structure instead of directly setting each field to get the same effect, as shown below:
Row = new {Customerid = "abcde", contactname = "frank", CompanyName = "acme"}; int N}}; int n = INSERT ROW INTO DB.CUSTOMERS
The UPDATE command is an expression that calculates the number of rows successfully modified due to the execution of this command. The following example shows how to make a global replacement of all spellings of the city "London".
INT n = update db.customers set city = "london" Where country == "uk" && city == "lundon";
You can also ignore the WHERE clause to modify all rows in the table. The delete command is an expression that calculates the number of rows successfully deleted due to the execution of this command. The following example deletes all orders of the customer of London.
INT n = delete o from c in db.customers inner join o in db.orders on c.customerid == o.customerid where c.city == "london";
Most applications using INSERT, UPDATE, and DELETE expressions are also using transactions to ensure ACIDITY (atomic, consistency, isolation, and persistence) for the database. The C-Omega language contains Transact statements that enhance the concept of initialization and exiting transactions in programming language features. The Transact statement is a statement that binds the code block related to the database transaction. If the code is successfully executed and attempts to exit the code block, the transaction will be submitted automatically. If you exit the code block due to an exception, the transaction will automatically abort. Developers can also specify using the CommT and Rollback handler. Once the transaction block is exited, the transaction block is executed. The following example shows some of the transactions being used:
Transact (DB) {delete from db.customers where customerid == "alfki";} commit {console.writeline ("commit");} rollback {console.writeline ("Aborted");} Using XML in C-Omega In C-Omega, an XML syntax construct object instance can be used. This function can be modeled after the language such as XQuery and XSLT is capable of constructing an element. Language such as XQuery and XSLT, XML can include embedded code for constructing values. However, since C-Omega is a static type, the name of the member and type must be known when compiling, and the dynamic configuration cannot be performed.
Many constructs can be used to control the form of XML. You can use the Attribute modifier in the member statement to specify that the fields in XML are deemed as attributes. Also, the selection type and anonymous structure can be considered as sub-elements of the XML element mapped to the content class. The following example shows how to initialize the content class in XML.
Using Microsoft.comEga; Using System;
Public class newsitem {
Attribute string title; attribute string author; struct {datetime date; string body;}
Public static void main () {
Newsitem news = {datetime.now} i am the first post of the new year.;
Console.writeline (news.title "by" news.author " news.date);}}
XML is designed to make the process of stronger type XML easier. Consider the following xQuery example (taken from W3C XQuery use case document). It loops accesses the books that contain many books. For each book in the book, it lists the title and authors, and groups in the Result element.
For $ b in $ BS / BOOKRETURN {$ b / title} {$ b / author}
The code to perform an equivalent task with C-Omega is shown below.
Foreach (b in bs.book) {
Yield Return {B.TITLE} {B.author}}
Small knot C-Omega language is an interesting attempt to build a bridge for typical enterprise development work in the "impedance mismatch" involved in the relationship, object-oriented and XML. Many of the language has been accepted within the academic circles and Microsoft, and the comments made in Anders Hejlsberg for the development direction of C # 3.0. Since then, developers can learn what to program more about data-oriented programming languages by downloading C-Omega compilers or Visual Studio.net plugins.
Acknowledgment Thank Don Box, Mike Champion, Denise Draper, and Erik Meijer INPORT and feedback provided when I wrote this article.
Dare Obasanjo is the program manager for the MSN Communication Services Platform team. He solves the XML problem with great enthusiasm to build a server infrastructure that MSN Messenger, MSN Hotmail, and MSN Spaces. For any questions or opinions on this article, please post to the extra XML message board on the GotdotNet.