Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples

Mono Unveiled

by Brian Jepson

GNOME and .NET are getting together. According to today's announcement, Ximian is working on Mono, an implementation of the .NET CLI. Although the .NET CLI is currently a small subset of the entire .NET framework, you can expect Mono to go beyond the CLI, as it will likely implement much of the framework in the near future.

As you know, Windows programmers are fond of creating large databases and linking them to user interfaces. Fortunately, GNOME has ways of doing this. Under Mono, the Windows Forms API will be implemented using the GTK+ user interface toolkit, and ADO.NET will be implemented using GNOME-DB.

Since Mono isn't complete now, all I can do is dream about this kind of stuff. So I decided to write similar programs in GNOME and .NET and see where the differences are.

Connecting to the Database

GNOME-DB and ADO.NET both rely on data providers, adapters between the client API and a back-end database. Since each database has a different API, a data provider maps that API to the GNOME-DB or ADO.NET API. Here's how to connect to SQL Server's pubs database using ADO.NET:

  /* This connection string specifies:
   *   Provider: OLE DB SQL Server provider
   *   Server:   Local machine
   *   Database: pubs
   *   User:     sa
   *   Password: (blank)
  String cs = "provider=sqloledb;server= 
  /* Make the connection. */
  OleDbConnection cnc = new OleDbConnection(cs);

Related article:

GNOME's Miguel de Icaza on .NET

This next listing shows you how to connect to PostgreSQL using GNOME-DB. Notice that you have to take a brief drink from the CORBA well to create a connection. This is because GNOME uses a high-performance CORBA implementation called ORBit (GNOME also provides the OAF Library to make it easy to deal with CORBA).

  GdaConnection* cnc;
  gchar *pg_provider = "OAFIID:GNOME_GDA_Provider_Postgres_ConnectionFactory";

  /* Initialize GNOME-DB */
  gnome_db_init("db_connect", "0.1", argc, argv);

  /* Use the ORB to create a new connection object. */
  cnc = gda_connection_new(gda_corba_get_orb());

  /* Make a connection to the database. */
  gda_connection_set_provider(cnc, pg_provider);
  gda_connection_open(cnc, "DATABASE=bjepson", "bjepson", "");

Fetching Data

Comment on this articleWhat do you think of Mono and its potential long-term potential for creating a complete open source .NET framework?
Post your comments

After you've made a connection to the database, you'll probably want to get some data out of it. Both GNOME-DB and ADO.NET use a command object to represent an SQL query. In ADO.NET, you create a command object and then associate it with a connection and SQL query:

/* Create a command. */
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = cnc;
cmd.CommandText = "SELECT * FROM authors";

After you have created a command, you can do a variety of things with it. The next example shows how to execute the query and process the results. Later, you'll see how to use a command object with a data adapter to fill a grid with data.

  /* Execute the command. */
  OleDbDataReader rdr = cmd.ExecuteReader();

  /* Display the results. */
  while (rdr.Read()) {
    object lname = rdr.GetValue(rdr.GetOrdinal("au_lname"));
    object fname = rdr.GetValue(rdr.GetOrdinal("au_fname"));
    Console.WriteLine("Name = {0} {1}", fname, lname);

In GNOME-DB, you also create a command and associate it with a connection and an SQL statement:

/* Create a command */
GdaCommand *cmd = gda_command_new();
gda_command_set_connection(cmd, cnc);
gda_command_set_text(cmd, "SELECT name FROM contact");

Instead of a data reader, you put the results into a record set:

GdaRecordset *rs;
glong rc;

/* Execute the command */
rs = gda_command_execute(cmd, &rc, 0);

/* Display the results. */
while (!gda_recordset_eof (rs)) {

  /* Retrieve the name field. */
  GdaField *name = gda_recordset_field_name(rs, "name");
  g_print ("Name = %s\n", gda_stringify_value(NULL, 0, name));

  /* Move to the next row. */
  gda_recordset_move_next (rs);

Connecting the Database to a Grid

You can attach objects from both GNOME-DB and ADO.NET to user interface components, such as a grid. Here is some .NET code that creates a Form and a DataGrid component (both are from the Windows Forms API):

Form window = new Form();   /* a window */

/* a data grid that expands to fill its container */
DataGrid grid = new DataGrid();
grid.Dock = DockStyle.Fill;

With ADO.NET, you need to use the command object to populate the grid. First, use the command to create a data adapter and fill a data set. The data set is an abstract representation of the results that can be used with user interface and XML components. The adapter is a broker between the command and the data set:

/* Create a data adapter. */
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);

/* Create a data set. */
DataSet ds = new DataSet();

/* Create a table called "results" inside the data set
 * and fill it using the adapter.
adapter.Fill(ds, "results");

Next, associate the DataGrid with the DataSet, and then run the application. (Figure 1 shows the DataGrid in action.)

/* Link the grid to the results */
grid.DataSource = ds.Tables["results"];

/* Run the main window. */

Screen shot.
Figure 1. The .NET data grid filled with data.

GNOME does things slightly differently. Instead of using the command object and helper classes, you can associate the result set with a GNOME-DB grid. When you create the grid, you need to pass the result set into its constructor (shown in bold). That's all the magic that's required to fill a grid with data (shown in Figure 2). This example shows how you can create the grid and display it in a GTK+ window:

GtkWidget* window;  /* a window */
GtkWidget* grid;    /* a data grid  */

/* Create the window. */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

/* Set up the event handler */

/* Create the grid and add it to the window. */
grid = gnome_db_grid_new(rs);
gtk_container_add(GTK_CONTAINER(window), grid);

/* Show the window and its widget */

/* Initiate the event loop */

Screen shot.
Figure 2. The GNOME-DB grid filled with the contents of a result set.


Download sample code:



One of the differences between .NET and GNOME is in the implementation of the grid component used with databases. .NET's DataGrid can be associated with a variety of data sources above and beyond database result sets (for example, you can use the DataGrid with any object that implements the IList or IListSource interface). The GNOME-DB grid, while flexible, is designed to work exclusively with database result sets.

Mismatches of this sort are sure to crop up as the .NET APIs are mapped to GNOME's, and the Mono developers will need to build .NET-compatible controls. In some cases, it will make sense to develop those as wrappers to existing GNOME controls. These wrappers could be written entirely in .NET managed code, in which case the new controls would not be available to GNOME programmers working outside of the Mono environment. In other cases, the Mono developers may end up refactoring existing GNOME components to make them more .NET-compatible. If they do this, then all GNOME programmers will have access to the enhanced functionality. This will be a tough judgment call to make; when should a GNOME component be enhanced to map more easily to .NET? Perhaps only when the change can be made without breaking backward compatibility, and when the enhancement will make the component more useful for GNOME developers.

Brian Jepson is an O'Reilly editor, programmer, and co-author of Mac OS X Panther for Unix Geeks and Learning Unix for Mac OS X Panther. He's also a volunteer system administrator and all-around geek for AS220, a non-profit arts center in Providence, Rhode Island. AS220 gives Rhode Island artists uncensored and unjuried forums for their work. These forums include galleries, performance space, and publications. Brian sees to it that technology, especially free software, supports that mission. You can follow Brian's blog here.

Return to the .NET DevCenter.

Copyright © 2009 O'Reilly Media, Inc.