Database applications are relatively easy with Xojo. The native Database, DatabaseRecord, and Recordset classes make it easy to connect, add, edit, and delete data in your console, desktop, and web applications. What we’ve found over the years isn’t that it’s hard to create these applications but that it’s tedious and also the very nature of Xojo tends to make life more complicated. Let me explain.
The Xojo database classes are very generic. To insert data into the recordset you either use an SQL Insert statement or use the DatabaseRecord class. The SQL statement, by itself if fraught with peril as it’s very easy to mistype the statement and miss it in testing. Even using PreparedStatements (which you should be using whenever possible) you can still screw it up. Using the DatabaseRecord class is more object oriented and without a doubt easier to use but it has one big problem: It doesn’t check datatypes. At design time it will happily let you try to put a date value into an integer field (depends on how you try, of course). It is not until runtime that you may get any sort error which leads to the next issue.
Database errors, at least in the global framework, do not generate exceptions. This means that unless you, the developer, check for the error, you may not get the results you expect. On an Insert statement, either using SQL or the DatabaseRecord, your data may simply never be inserted and you’ll never know it unless you’re checking the Error property on the database connection. The Error must be checked after EVERY SQL action whether that be SQL Select, Insert, or Delete. Even checking after a Prepare statement is wise to do so.
The good news (maybe) is that Xojo for iOS and the iOSSQLiteDatabase class will throw an exception if it experiences a database error. It’s good that you don’t need to check for the error manually, but now you need to put in exception handling around your database code and deal with exceptions accordingly. It’s not hard, but it’s also not trivial code either.
The IDE knows next to nothing about the database and certainly when you code it you have to query the database for Table and Field schema’s. To make it worse, the Xojo database framework has no idea about the concept of Views requiring you to query the database specifically to find and learn more about them. The IDE has no idea about the field datatypes either and the compiler can’t warn you about mismatched datatypes. These types of errors are only caught at runtime which is usually way too late in the process (hopefully not by the client either).
The database frameworks are not very object oriented friendly. If you have a simple Add/Edit dialog you need to know if the record is new, or not, since this changes how you code saving the data. New requires the DatabaseRecord object and an existing record can be updated via the Recordset object (both can use SQL statements but the statements themselves require different statements).
Xojo is easy to use but the ability to stick code in control events tends to make big database applications unwieldy and full of spaghetti code. Changing a field name in a commonly used table, or even worse changing the field datatype, is often at your own peril because you might have SQL statements referencing it in hundreds of places in the code. Forget it one place and you have an error in the waiting.
Finally, there’s the hooking your user interface up to your database code. Many people have Load/Save methods in every window/dialog/container that needs it. Use a SQL statement to get the data, then use the Recordset to load the user interface, and then use a Save method (that knows the difference between new and existing records) to put it back into the database. Again, the IDE compiler can’t help you if you make either a spelling mistake in the SQL statement or Field names so you won’t find these errors out until runtime (which is often too late).
There are options, to all of these problems. Creating your own data classes is a step above the standard Xojo code, in my opinion. You encapsulate a record into a Xojo class and implement your own Load and Save methods. This is a better object and forces some compiler warnings into your code. It also tends to put your database code all in one folder and/or NameSpace. You can use field name constants for field names, and force all db code into one class or module. Unfortunately, if you have hundreds of tables it’s also tedious to do all this.
There are other solutions out there, but ARGen takes some of the tediousness out of the work of creating a Xojo database application and does some other nifty things too like creating a basic User Interface for you.. ARGen is short for ActiveRecord Generator. ActiveRecord is a set of classes that map the database into equivalent Xojo namespaced classes.
Say you have a table named Employee. ARGen would create a class named ‘Employee’ in the ‘Data’ namespace and you would reference it in code as Data.Employee. Each field in the table is then mapped to a property in the class. The FirstName text field would be mapped to a string property named “FirstName”. This property is referenced as Data.Employee.FirstName and since the compiler knows this property is a string it will complain if you try and put an integer into it. Since there’s only one place you would ever define FirstName in your project it becomes really easy to change the name or change the datatype and then have the compiler catch any errors. It also means that AutoComplete in the code editor works meaning you’ll never mistype a table or field name again without the compiler catching it.
When an ActiveRecord project first starts up and connects to the database we call a Register method that calls out which tables/views are added into ActiveRecord. ActiveRecord scans the schema of the table and then attempts to match up every field with a corresponding property on the class. If a field is missing from your class it will generate an error that’s caught only while debugging (a “table x is missing field y” type of message).
Each ActiveRecord instance is a complete record. It has built-in Save and Delete methods. It also has events for Before and After Create, Before and After Update, to let you do things globally for each record. One example we use all the time are CreatedBy, CreatedDate fields in the Before Create event and ModifiedBy and ModifiedDate fields in the Before Update event. One place, ever, to put that data into the database rather than the potential thousands of places it might. There is also a convenient IsModified method to figure out if data has actually changed or not.
The Save method knows if it’s a new record or an existing record and does the right thing behind the scenes for you. Using a transaction, using a PreparedStatement. I think this one feature alone saves us hundreds of hours of coding because it’s a simple Save call. Nothing more be done. It really takes the worry out of it.
There are other coding features that we could get into but it all revolves around making creating database applications in Xojo fast and easy. ARGen creates a bunch of helper functions like IsDuplicate, List, and so on to help make your life easier. ARGen has a free mode which allows you to get the ActiveRecord classes and up to two tables at a time done.
For many years this is all ARGen did and we used it with great success. However, we found ourselves spending a lot of time on the next step – creating windows, dialogs, and containers and hooking up the database classes to the User Interface. Practically every table you run across has a List and Edit form. In version 2 we added the ability create a rudimentary User Interface which saves even more time. You only get this ability with the fully paid version.
When generating a Xojo project ARGen puts in a number of #pragma error statements where the developer needs to look at code and uncomment code and/or fix code. It’s hard to guess and frankly we don’t want your newly generated project to compile without you having to fix some code. Trust me – it’s better this way. There are simply too many variables and ways of doing things. Because of the #pragma error statements I like to bring over classes and UI over from the generated project as I need them rather than all at once. No need to fix hundreds of pieces of code until you’re ready to look at them.
ARGen and ActiveRecord isn’t perfect and it’s not the only solution around. ARGen lets the compiler do some work for you and eliminates some of the very common, but trivial, mistakes. It also lets you save a ton of time when it comes to standard database code and building user interfaces. It isn’t a panacea for development but ARGen can save you a lot of time and effort.
If you’d like to learn more about ARGen and what it can do for you, please download the free/demo version from the product page at http://www.bkeeney.com/allproducts/argen/. There are several videos on the ARGen menu that show more details.
Update: I did a Xojo webinar a while back that talks about some of this in detail. It’s a little dated but worth watching: http://developer.xojo.com/webinar-simplying-db-access-with-bkeeney-activerecord