Yes, it’s done. I’ve finished putting the finishing touches on the smart client offline application block. All that remains is to figure out a cool name for the project. In any case, I’d post the code and a demo application at Codeproject.com tonight. In the meantime, here’s some of the paper work I finished.
Benefits of the new SOAB
- Simplified Deployment
No SQL Servers to deploy, no database scripts to run, no logins to create; simply application where you want and run it. The cache and queue databases will be created on the fly the very first time it’s needed. It’s that simple!
- Inter-dependant queue elements
Imagine a smart-client application used for cataloging books. The central server maintains a catalog of book and authors. For a book to be cataloged, its author must exist in the database. (Exactly how such an application would be useful is of no concern to us here :). The smart client downloads the list of authors from the server when it goes online. A problem arises when a book along with its author has to be created offline. When an author is created offline a “Create Author” request is queued in the command queue. Likewise, when a book is created a “Create Book” request is queued. The new SOAB provides a mechanism by which the programmer of the smart-client could specify that a “Create Book” request should be executed (transferred to the web-service), only once its related author object has been successfully put on the central database.
- All the glory of Db4O
Db4O is a powerful Object Database, with advanced functionality such as native query, SODA query, etc. etc. While the SOAB.Data.Database class attempts to wrap most of the interactions with the underlying Db4O Object Container, it is still accessible to the brave-hearted. This opens up number of additional possibilities such as modifying/deleting individual items from the queue, querying for specific items in the cache or the queue, determining which items are to be modified when the queued elements are executed etc.
- Tiny Code base, built on .NET 2.0
The application block has only about 15 classes and interfaces in total: Out of which only 6 you’d need to concern yourselves with. You’d probably take less than 2 hours to identify how to harness the full potential of the SOAB. The new SOAB uses generics, and the new event-based asynchronous invocation methods, breaking away from the old way of doing things.
Working with the SOAB
Working with the SOAB is almost effortless; simply follow these few steps
- In your smart-client application, add a class derived from SOAB.ServiceAgent. In the sample application I have made this derived class (ServiceClient) a singleton. While this is not always required, it might be a good idea to do so.
- Create a ServiceContext class and keep it around as it can be used for all service requests. Since, the ServiceClient is a singleton, I’ve made the ServiceContext instance, on of its fields. The ServiceContext class is basically a builder for your web-service proxy class. Make sure that you pass the fully qualified class name of the proxy to its constructor.
- When you need to invoke a web method, create and populate a ServiceRequest object and enqueue it using QueueManager.Instance.Enqueue(…) method. To populate the ServiceRequest assign;
- The ServiceContext instance to the ServiceRequest.ServiceContext property.
- The name of the web-method you are invoking to ServiceRequest.RemoteMethodName.
- The argument to the web-method to ServiceRequest.Payload.
- The name of a method accepting a ServiceResponse argument belonging to the ServiceAgent derived class to ServiceRequest.CallbackMethodName.
The method specified in the CallbackMethodName property, is invoked once the ServiceRequest has been executed. You should use the properties in the ServiceResponse object passed on to the method to determine whether the request was successful, cancelled or whether it generated an exception. If you have any object types that might depend on other objects (such as Book that depend on Author), you should implement ICacheDependant interface on the dependant class. Provide the dependency resolution logic in the IsResolved property-getter and return true if the object is ready to be transferred to the web method.
Words to the Wise
Please note that this is my first complete project using Db4O. So, the Db4O-related code might not be optimal. For instance, I’ve used ReaderWriterLocks for guarding object container read/write actions. However, the database itself has built in locking mechanisms which I could’ve used for the same purpose. Hopefully, somebody who’s more experience with Db4o can offer some assistance …?