With the Q2 Release of RadControls for Windows 8 we announced a new Data Storage framework that fills the gap of a local database solution missing in Windows 8/RT. Our solution is based on the well-established SQLite engine but provides additional functionality. Particularly, we implemented a LINQ to SQLite provider and some simple ORM features for the .NET Framework on top of it. On the JavaScript and HTML 5 side, the ORM capabilities are wrapped by a lightweight library which allows JavaScript developers to take advantage of the local database storage using JS objects and standard SQL expressions.

Even though built on top of SQLite, Telerik Data Storage is not a simple SQLite wrapper for Windows 8. We've tried to bring together the flexibility of SQLite with the ease of use of .NET and JavaScript. As a result, the component strays from the typical SQLite programming model towards a friendlier, more familiar set of technologies inherently familiar to .NET and JavaScript developers. Automatic schema inference, LINQ support in .NET, asynchronous Promise-based development in JavaScript are some of the features that make developers feel right at home. The result is a tool that feels natural to use in the target development environment.

Using the Data Storage component in C# and .NET

Let’s give some simple examples and see the Data Storage solution in action. There is the Context class that wraps everything you need to apply CRUD operations or manipulate the database. To open or create a database with name “MyDB”, located at the local isolated storage, the following initialization of a Context instance is enough:

var context = new Telerik.Storage.Extensions.Context("MyDB", DatabaseLocation.Local);

Then let’s create an entity class named Person:

class Person
{
   [System.ComponentMode.DataAnnotations.KeyAttribute]
   public long PersonID { get; set; }
   public string Name { get; set; }
   public int Age { get; set; }
   public bool Alive { get; set; }
}

Here we specify the primary key field of the table that will correspond to this entity class with [Key] annotation. Primary key definition for any entity class is mandatory. We can additionally mark any field as auto-incremented by adding the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] data annotation.

The following code shows a simple insertion of a data object into a table that maps the properties of the entity class Person. The first insertion of an object from a particular entity type automatically creates the underlying SQL table if one doesn’t already exist in the database. Otherwise it updates the existing table’s schema. The table’s column names map to public properties of the entity class. The name of the table itself matches the name of the entity class.

context.Insert(new Person() { PersonID = 2, Name = "John", Age = 78, Alive = true });
context.SaveChanges(); //persist context’s changes into the database

Once we have some data in, the user can apply select, update or delete operations on the persisted data. While this can be done using regular SQL queries in the SQLite dialect, we've additionally provided LINQ support for select queries. For example:

string query = "UPDATE Person SET Name = 'Mike' WHERE Name = 'John'";
var t = await context.GetScalarAsync<int>(query);

To get all persons with name “John” :

var p = context.Get<Person>("select * from Person as x where x.Name == @p0", “John”);

This is equal to the following LINQ query:

var t = from item in context.GetAll<Person>()
    where item.Name == "John"
    select item;

or

var f = context.GetAll<Person>().Where<Person>(p => p.Name == “John”);

As shown in the above example, you can use parameterized expressions as a convenient way to build queries based on dynamic data.

Using the Data Storage component in JavaScript

JavaScript developers get the same set of API goodness. Everything that .Net programmers can do with the database has its equivalent in JavaScript too. The first version of our JavaScript library exposes a thin wrapper on top of our ORM engine and allows complicated CRUD operations via data objects and SQL queries. The examples shown above can be written in JavaScript as follows:

var db = Telerik.Data.Database.open("MyDB", "local" );
var person = { id: 2, name: 'John', age: 78, alive: true};
db.insert('persons', person);
db.sync().then(function () {
        db.close();
       });
db.query("select * from Persons where name == 'John'").then(function (result)
        //do something with the result object
        db.close();
       });

Asynchronous Database Requests

An important aspect of developing with the Telerik Data Storage APIs for Windows 8 is the built-in support for asynchronous database operations in both .NET and JavaScript. While our extensive performance tests (involving tens of thousands of data records and heavy join and group queries) show very good performance results even on low-end devices, some queries may involve heavy, time-consuming data processing. In such scenarios UI responsiveness can be maintained using well-established practices of asynchronous programming.

The .NET API supports the Task-based asynchronous pattern based on the System.Threading.Tasks namespace. A set of async methods for database operations return either a Task or a Task<TResult>, based on the return type of their equivalent synchronous methods. For example, the set of synchronous methods:

public void SaveChanges();
public ScalarType GetScalar<ScalarType>(string query);

have corresponding async method definitions:

public async Task SaveChangesAsync();
public async Task<ScalarType> GetScalarAsync<ScalarType>(string query);

In JavaScript, all operations involving communication with the database are wrapped in Promise objects implementing the asynchronous flow of execution. As shown in the previous JavaScript code example, the sync()and query(queryString)methods of the JavaScript database object are asynchronous.

How is the Data Storage Component bundled?

The CTP version of the Data Storage component is available in two separate packages: one for XAML/C# and one for JavaScript/HTML. Each package includes an SDK, a sample application that demonstrates typical database usage, and a document, providing brief overview of the framework and its usage. The demo application implements a simple solution for sales management of bike stores chain with visualization of aggregated data for sales analysis. The code base shows different well described approaches for CRUD operations and uses the RadGrid and RadChart components from our RadControls for Windows 8 suite for rich data visualization. Exploring this application is a good starting point for developers and a good integration example, demonstrating how well do RadControls for Windows 8 and the Data Storage component complement each other.

Here are some screen shots of the sample application:


Figure 1: The "Home Screen" of the application


Figure 2: "Total Sales by Location" page


Figure 3: "Sales by Month" page

How Telerik’s Data Storage solution compares to other available free libraries that use the SQLite engine?

There are other SQLite wrappers for .NET and Windows 8 available out there, but none of them is as feature rich as Telerik’s Data Storage. The following table compares major features supported by different SQLite wrappers that can be used for application development for Windows 8/RT:


Conclusion

On the .NET side the usage of Telerik’s Data Storage is closer to a LINQ –to-SQL programming model and ADO.NET with its ORM features. Still, the component doesn’t deprive users of SQL queries too, should they need maximum flexibility. On the JavaScript side, having a robust, extensive, multi-purpose, local data storage solution enables non-trivial data-centric app development using the Windows 8 web stack. We believe the Telerik Data Storage component will become an essential tool for developers building data-oriented Windows Store applications.  Do not hesitate to grab your copy of Telerik’s Data Storage solution and give it a try. The library is in an early CTP version and we are really eager to get your feedback on what can be added, improved or extended.


About the Author

Georgi Atanasov


Related Posts

Comments

Comments are disabled in preview mode.