Investigating .NET Page 9

ADO.Net

There’s an important part of .Net that I haven’t mentioned yet, which is its database libraries. Microsoft is famous or rather notorious for having lots of database libraries. Let me see, there is the original and immortal ODBC, then there is Data Access Objects, Remote Data Objects, OLE DB and Active Data Objects, which covers the main ones I think. Anyway, ADO.Net is completely new. As with ASP.Net, don’t be fooled by the name; it is nothing whatever like the old ADO.

I found ADO.Net pretty confusing at first, so I’m going to start by telling you the two things that helped me to understand it.

First, ADO.Net uses a disconnected model. You grab the data, disconnect from the database server, and work with the data locally. At some later stage you might update the database server from your local data. That’s why ADO.Net doesn’t have any handy updateable recordsets, where edits automatically get posted to the server. The disconnected model takes a bit more effort to program, but it’s excellent for distributed applications and web applications where you can’t rely on a fast, robust network connection.

Second, the ADO.Net libraries actually implement a local in-memory database manager, confusingly called a dataset. As a database manager, it supports things like indexing, searching, updating, and referential integrity. But its features, naturally enough, are independent of the database server that happens to supply the data. This is why ADO.Net can catch you out. You might have cascading deletes implemented in the database, but your local ADO.Net database doesn’t know about that. You might have constraints such that the customerID field in the Orders table must exist in the Customers table, but ADO.Net won’t automatically know that either. It’s down to you to manage your local data sensibly so that it doesn’t blow up when you try to update the server.

ADO.Net is heavily XML-centric. Database schemas are stored as XML schemas, and data can be persisted to disk or to any stream using XML. This can keep a record of edits and updates as well as the current state of the data, which makes it easy when it comes to updating the server.

If you don’t want to work with ADO.Net datasets, you can also use straight SQL Selects and Executes to manage data. Often not a bad idea in my opinion. When you do a SQL SELECT, the datareader classes give you a fast, forward-only result table.

Databinding is very well implemented in the .Net Framework. In other environments I’ve found databinding more trouble than it’s worth, but in .Net it works really well. The key point here is that you can bind controls like listboxes and grids to any object collection, not just data tables. So what I do is to use a datareader to grab data, use it to instantiate a collection of custom objects specific to my application, and then use databinding to display the objects in tabular form.

A problem for ADO.Net is that competing database vendors have not hastened to provide the necessary managed code drivers, although Oracle has done so. Generally speaking, the best database to use with ADO.Net is Microsoft SQL Server, which is a bit monochrome. There is an ODBC driver and an OLEDB driver, so most databases should be accessible, it is just a matter of performance and perhaps access to database-specific features.

Where next for COM and Win32?

In theory, the .Net Framework replaces COM and the Win32 API. However, it’s not that simple. First there’s the matter of interoperability between the .Net Framework and existing components and applications. Second, the Framework itself makes heavy use of PInvoke and Com in implementing some of the classes, particularly when it comes to Windows Forms.

According to Microsoft’s publicity, COM interoperability is a snap. A little tool called tlbimp, or the Type Library Importer, creates a managed code wrapper for any COM component. You can also host ActiveX controls in .Net Windows Forms. Going the other way, you can take a .Net assembly, and use a tool called Regasm to expose it as a COM component. Then you can call it from COM clients such as Visual Basic 6.0.
In truth, the COM interoperability in .Net is remarkable but not as easy or seamless as this happy picture suggests. First there is understandably a performance issue. Each call across the .Net/COM boundary has an overhead, and although it is small, it can have severe results if your API is “chatty”, that is, requiring many short calls. More seriously, the tools are not quite the miracle workers that their description suggests. If you go into the matter in depth, you find that while the type library importer has a good go at creating a .Net wrapper, it may not be successful and it may well not be optimal. You can get better results by manually editing the wrapper, or by creating your own wrapper from scratch. You can do custom marshalling to make difficult interfaces accessible. Even then, a few things may not work.

There’s another aspect to COM interoperability. COM as most of you will know is all about interfaces. In advanced COM work, your application has to implement particular COM interfaces in order to work with a COM API. You can implement a COM interface in C# or VB.Net, but it’s not necessarily easy. Programmers find themselves manually defining COM types in C#, experimenting with different marshalling options trying to find one that works. Usually they succeed; but you should never assume that COM interop is going to be straightforward.

In VB 6.0 programmers got used to the idea of calling the Windows API to get certain tasks accomplished. The same is true in .Net. In its first release, the .Net Framework has no support for sound or multimedia. It’s coming in the next version of DirectX, but in the meantime PInvoke is the only way.

There’s also no sign of Microsoft moving away from C++ and COM for its Office or consumer applications. I believe it will do so, but probably not for a couple of years. What this means is that neither COM nor the Win32 API is going away. .Net programmers, especially with Windows Forms, will have to get used to PInvoke and COM Interop. For Web applications that’s less true. You can probably do all you need without PInvoke.

Next