ierDeveloper is an Object-to-Relational (O/R) mapping tool that integrates with Visual Studio versions 2002 and higher. TierDeveloper maps Relational Database Management System (RDBMS) tables to .NET objects (VB.NET and C#), so that a programmer needs only to "get" and "set" an object's properties to retrieve or store it, without needing to know that it's underpinned by a database at all.O/R mapping is something of a half-way house between relational and object databases. On the one hand, it's able to leverage many of the benefits of a "pure" object database, like strongly typed objects and transparent persistence, meaning that developers can navigate and update the database without writing a single line of SQL. On the other hand, it lacks some of the caching and performance benefits of a genuine object database management system, because although usually concealed by an API, type coercion between object types and native database types still has to take place. In contrast, a genuine ODBMS usually has a one-to-one mapping of object-to-database types, and therefore has no such performance hit.
But O/R mapping isn't really a "killer app" in itself, so TierDeveloper tries to go a bit further, taking the object/table bindings you've specified and generating skeletal WinForms, WebForms, Web service, and remoting applications on request. The resulting applications can target SQL Server, Access, Oracle, and DB2 databases.
Boot up TierDeveloper, and you'll be greeted by an IDE strikingly similar to Visual Studio. Assuming you're connected to the Internet, the content pane will walk you through the process of creating a project (if you're working offline, you'll get the somewhat less helpful "This page cannot be displayed.")
But you're only a few mouse clicks away from a complete application. Use the File menu to start a new project, and TierDeveloper prompts you to select a database. When you select the database, TierDeveloper "acquires" a list of tables within it. All you have to do is click "Project> Components> Generate & Build" to create object mappings for each table, and then "Project> WinForms Application> Generate & Build" to produce a standalone executable. For various reasons I was unimpressed by the final applications TierDeveloper produced, but I'll come to that in a moment. What struck me first was that TierDeveloper's O/R mapping was based around a sensible object model, and a lot of thought had gone into making it as flexible as possible.
Mapped and Unmapped Objects
At the heart of any TierDeveloper project is its collection of "Objects" (capital O). These will ultimately be compiled into .NET classes, and you'll use them to interact with the database. But TierDeveloper's O/R mapping isn't just database driven; it's actually two-way. You can map objects from a database, or alternatively declare "unmapped objects" with appropriate properties and export DDL scripts to create the necessary database tables. The resultant objects usually represent one or more fields mapped from one or more tables, but you can also combine unmapped objects with a "User Defined" schema synchronization to produce auxiliary "non database" objects. Whichever approach you choose, you can then further refine the resultant .NET objects with additional queries, relationships, and stored procedures as described in the following sections.
|Author's Note: Watch out! If you do create unmapped objects and choose to export DDL scripts for them, be sure to uncheck "Export Data Source tables" (checked by default) if you don't want your database tables emptied of all their existing data when you run the resultant script.
For fine-grained control, you can add queries to the objects you've created. While you're free to enter your own SQL explicitly, the process is wizard driven and the dialogs open with appropriate defaults and constraints. For example, if your query doesn't involve a JOIN
, you're restricted to the data types already exposed by the object in question. If, on the other hand, you elect to JOIN
another table, TierDeveloper tries to guess the correct foreign key and choose it automatically as a default. Having chosen the table bindings, you can enter an explicit WHERE
clause if you want. Alternatively, you can elect to generate a "Dynamic Query", meaning that the WHERE
clause is supplied at runtime by the application.
You can also add one-to-one, one-to-many, and many-to-many relationships between the tables mapped by your objects. A nice touch is that if you check "Show only Related Objects," TierDeveloper displays only the database tables that match the relationship you've selected, showing the column keys side by side. For many-to-many relationships, it cleverly attempts to identify the bridging table in question. I also liked the fact that if you try to add a relationship to a table that isn't yet mapped, TierDeveloper offers to import a mapping for it automatically, before creating the relationship. The wizard is intelligent enough to detect improbable mappings (for example, if you try to map int
, and issues an appropriate warning.
Stored Procedures and Bulk Operations
TierDeveloper lets you wrap stored procedures as method calls and add dedicated functions to update or delete records (based on an input parameter). The interface for doing this is similar to the one you use to create queries.
With a full set of mapped objects, you should be able to replace your legacy SQL with .NET objects whose methods and relationships manipulate and represent the database in the same way. It's one thing to create objects based on a snapshot of a database table (or vice versa), but keeping those objects and the underlying database structures synchronized is typically more difficult; however, TierDeveloper makes this particularly easy. After linking a TierDeveloper project to a particular database, you can resynchronize the two at any point. This means that TierDeveloper propagates "online" changes to the database (e.g. manual updates via SQL Agent) to the "offline" TierDeveloper project, and "offline" changes to the project to the database. You can set synchronization on a per-object basis, or choose "User Defined" for standalone objects or those with complex synchronization semantics.