One of my first questions when starting to develop on Windows 8 was what do I use for local storage. It seemed like a lot of the samples were geared to consuming public web apis/services and that is certainly a valid use case. But a lot of “traditional” desktop apps (particularly LOB applications) are going to need a local data source. From what I’ve seen there are three main scenarios that are fairly common in Windows 8 applications.
- Consuming public data through web services (as mentioned above). This could be data like Twitter or Flickr or more specialized business services.
- Use some type of cloud storage, such as Azure or AWS. This is fairly common and is really a specific variation on scenario 1.
- Use a local database or data source. This can really be anything you can write a data layer against or even just static JavaScript arrays.
For scenario 3, there are a number of choices you can pick from, but it has to be something file-based because it ends up getting stored in Local Storage. So that means SQL Server Compact or more frequently SQLite. Part of the reason SQLite is becoming popular for this is because it is already a popular choice for mobile and iOS applications, so there is already some open source frameworks and tooling around it. It’s also fairly robust, doesn’t require configuration and supports transactions. I’m starting to see a lot of questions around how to use it, since most Windows developers haven’t really been exposed to it. I certainly hadn’t, but if you are familiar with other relational databases you probably won’t have much trouble picking it up.
In a recent application we were working on at Clarity, we decided to use SQLite. Part of the reason is because the application was an iPad application port, but now that I’ve used it I would be pretty likely to pick it again. We iterated through a variety of patterns and architecture, but ultimately decided writing a data layer in JavaScript was just not that much fun. There are some JavaScript or PHP frameworks for SQLite, but if you are used to LINQ and working with a typed language you can be a lot more productive using .NET for your business services and data layer. So we ended up going in that direction and here’s a brief overview of this architecture.
To give credit where credit is due,a lot of good ideas for this solution came from Nathan Winder,as well as George Durzi and Matt Hudson. There were a lot of false starts and refactoring along the way to end up with this architecture.
- SQLite database
- In our application, this database was actually synced from/to a master database in Azure, but i won’t be covering that here.
- POCO objects corresponding to tables and views in the database. NOTE: your object datatypes must be WinRT consumable types. Also, SQLite isn’t really strongly typed in the way SQL Server is, so you have to be a little more careful about making assumptions on what type of data you are going to get from an int field or whatever. One thing that throws people off is there is no DateTime type in a WinRT component, you must use the DateTimeOffset type.
- sqlite-net open source library to provide a lightweight LINQ implementation for querying the database. This doesn’t have all the features you might be used to in the SQL Server provider, but you have the source so you can enhance it yourself.
- C# WinRT component that acts as a data layer, business services layer and provides a single point of entry for the JavaScript application.
- LocalDataRepository – typical CRUD operations against the SQLite database
- Models – model classes for your domain objects, which map roughly to the core tables in your database. The models also provide access to related objects (i.e. if you have a music Album model, you can ask for the Tracks on the album). We used a ModelReferenceManager that provides a weak reference to the model that can be accessed globally throughout the application. This allow models to access their parents with holding a direct reference, which simplifies serialization. This becomes important when you are suspending and rehydrating your application and you have a large data model in memory. But it isn’t absolutely necessary.
- ApplicationModel – this isn’t set up as a true singleton, but the JavaScript application creates an instance of it on startup and after that all operations go through that instance. You do have to be careful when suspending and resuming to make sure only one application model is available.
- Locator – This is the entry point for the JavaScript application, providing references to the main layers of the WinRT component, such as the ApplicationModel, the LocalDataRespository, user or security objects, the logging framework and so on.
This is a very high level overview of the architecture and probably doesn’t explain everything, so we thought it would be helpful to write a sample application showing the concepts. The sample uses the open source Chinook database, which is an alternative to Northwind that has a SQLite version. This database uses music information pulled from an iTunes library. To keep things simple, our app uses an artist – album – tracks flow through the application, using the JavaScript application navigation template. To keep things interesting, we also implemented semantic zoom on the first screen (there are a lot of artists) and a search tracks feature using the Search charm.
You can get the solution via the Visual Studio 2012 online gallery as a VSIX extension or in the Extensions – Templates gallery online. This will install the solution as a project template that you can select under the JavaScript category in the Create New Project dialog. The solution contains 3 projects: the Javascript Windows 8 application project, the C# WinRT component project and the sqlite-net project. Although you can include the sqlite-net project through GitHub, we made a couple of changes to the source so it was just easier to include the source directly. NOTE: You will need to set the target platform for all 3 projects to x64L in the build configuration manager before running the application.