Windows 8 WinRT SQLite
Depuis Windows 8 Preview, nous avons accès à une base de données déployable et interne, facile d’accès directement dans votre package WinRT.
On aurait pu s’attendre à voir débarquer SQL Server Compact, mais c’est bien SQLite qui sera supporté et accessible dans Windows 8.
Nous allons voir ici comment installer et travailler avec ce petit moteur de base de données extrêmement connu dans le monde du web notamment.
Installation
Cette première partie d’installation est inspirée d’un article écrit par Tim Heuer, que vous pouvez retrouver sur son blog, in english in the text ![]()
L’installation de SQLite se fait directement depuis le menu TOOLS de Visual Studio et le sous-menu Extensions And Updates.
Par ce biais, vous aurez accès plus tard directement aux mises à jour de SQLite, sans avoir à vous en préoccuper. Deuxième chose, ce package est capable de correctement cibler votre configuration, que ce soit x86, x64 ou ARM.
Faites une recherche sur SQLite, vous devriez trouver facilement l’extension, qui s’installe via VSIX :
Il ne reste plus qu’à :
- Créer un projet de type Windows Store (XAML C# dans mon cas)
- Référencer l’assembly SQLite
- Référencer le C++ runtime. (Obligatoire si la machine cible ne le possède pas, trés rare, et qui potentiellement vous ferait échouer la validation de votre apps)
Avant d’aller plus loin, si vous lancez la compilation de votre projet, vous risquez fortement d’avoir deux erreurs, pour le moins explicite:
Autant SQLite va savoir déployer la bonne dll suivant votre configuration, autant il vous faudra quand même avoir en target la bonne version (x86, x64 ou ARM)
Exit donc la configuration si pratique ANY CPU. Dommage …
Où en sommes nous ?
Nous avons installé SQLite, tout du moins le moteur et la runtime, compatible avec WinRT.
Il nous faut maintenant un Framework d’accès à SQLite. Il en existe plusieurs et j’ai choisi pour l’instant d’utiliser un projet Github, accessible via NuGet : sqlite-net.
(Je surveille de prés aussi le projet Sytem.Data.SQlite for WinRT. Il semble en bonne voie, je vous en reparle plus tard)
L’installation de sqlite-net est simple, elle vous rajoute 2 classes SQLite.cs, et SQLiteAsync.cs
N’hésitez pas d’ailleurs à y jeter un coup d’œil, c’est une mine d’informations.
A partir de là, votre environnement de travail est prêt et vous pouvez commencer la partie la plus intéressante : votre code ![]()
Connexion
Il faut savoir qu’ouvrir une connexion à SQLite crée un lien avec votre base de données locale mais aussi, crée la dite base de données si celle ci n’existe pas !
Pour créer une base de données SQLite, il vous faut cependant bien “placer” le fichier sqlite au bon endroit, soit le Windows Local Folder du package.
Voici un code minimaliste d’ouvertur de connexion (et donc de création de la base locale)
// Open a new Connection to SQLite. using (var connection = new SQLite.SQLiteConnection(dbPath)) {}
Note : J’ai eu quelques soucis avec cette méthode, notamment si vous avez un caractère unicode dans le chemin d’accès de votre package.
Par exemple, mon compte utilisateur contenant un accent, “Sébastien”, cette méthode d’ouverture ne fonctionne pas !
Je vous conseille donc de passer par la surcharge du constructeur, qui elle, fonctionne
// Open a new Connection to SQLite. using (var connection = new SQLite.SQLiteConnection(dbPath, SQLite.SQLiteOpenFlags.Create | SQLite.SQLiteOpenFlags.ReadWrite)) {}
A partir de là, votre base de données est créée. Certes elle est vide pour le moment ![]()
Outil d’administration
Pour ouvrir une base de données sqlite et l’administrer, il existe une multitude de produits. Je vous conseille SQLite Spy qui est loin d’être le plus complet, mais qui est celui qui semble le plus léger et surtout qui fonctionne a peu prés correctement avec la dernière version de SQLite (si vous avez mieux, je suis preneur
)
Notre base de données se trouve dans le répertoire où sont stockées les packages Windows 8. (AppData / Local / Packages / ID Package / LocalState)
Dans mon exemple, il se trouve ici :
Travailler avec des tables SQLite
Pour faire simple dans cette première présentation, nous allons via SQLite Spy, créer une table Client et tenter de la requêter depuis notre application WinRT.
Note : Nous verrons plus tard que sqlite-net contient des outils de mapping permettant de directement créer une table à partir d’une entité. Mais pour le moment, continuons avec les bases…
Requête de sélection non paramétrée
Une fois la connexion ouverte, il suffit de :
- Construire une requête
- Préparer la commande (qui renvoie un IntPtr que nous appelerons SQLite3Statement)
- Parcourir l’ensemble des lignes retournées
- Récupérer les valeurs
- Finaliser la commande
List<Client> lstClients = new List<Client>(); // Open a new Connection to SQLite. using (var connection = new SQLite.SQLiteConnection(dbPath, SQLite.SQLiteOpenFlags.Create | SQLite.SQLiteOpenFlags.ReadWrite)) { const string querySelect = "Select * from Client"; Sqlite3Statement stmt = Sqlite3Statement.Zero; try { // Prepare command stmt = SQLite3.Prepare2(connection.Handle, querySelect); // While row is available while (SQLite3.Step(stmt) == SQLite3.Result.Row) { Client client = new Client(); // Get values client.ClientId = SQLite3.ColumnInt(stmt, 0); client.FirstName = SQLite3.ColumnString(stmt, 1); client.LastName = SQLite3.ColumnString(stmt, 2); client.CreationDate = DateTime.Parse(SQLite3.ColumnString(stmt, 3)); client.Age = SQLite3.ColumnInt(stmt, 4); lstClients.Add(client); } } catch (SQLiteException ex) { Debug.WriteLine(ex.Message); } finally { // Finalize statement SQLite3.Finalize(stmt); } }
Requête de sélection non paramétrée
Le passage de paramètre est relativement classique avec
D’une part la construction de la requête prenant un paramètre, représenté par un point d’interrogation :
Select * from Client where LastName = ?
D’autre part un mécanisme de Bind de paramètre coté code (le paramètre étant repéré via son index, attention à ce détail)
Attention : Index de base 1 !!!!
// Bind parameter SQLite3.BindText(stmt, 1, lastName, -1, new IntPtr(-1)); SQLite3.BindInt(stmt, 2, 12); SQLite3.BindDouble(stmt, 3, (double)12); SQLite3.BindNull(stmt, 4);
sqlite-net apporte une méthode globable, plus simple à utiliser et qui prend en compte tous les types de données classiques:
SQLiteCommand.BindParameter(stmt, 1, lastName, false);
Le code de récupération des clients par le nom devient du coup :
List<Client> lstClients = new List<Client>(); // Open a new Connection to SQLite. using (var connection = new SQLite.SQLiteConnection(dbPath, SQLite.SQLiteOpenFlags.Create | SQLite.SQLiteOpenFlags.ReadWrite)) { const string querySelect = "Select * from Client where LastName = ?"; Sqlite3Statement stmt = Sqlite3Statement.Zero; try { // Prepare command stmt = SQLite3.Prepare2(connection.Handle, querySelect); // Bind parameter SQLiteCommand.BindParameter(stmt, 1, lastName, connection.StoreDateTimeAsTicks); // While row is available while (SQLite3.Step(stmt) == SQLite3.Result.Row) { Client client = new Client(); // Get values client.ClientId = SQLite3.ColumnInt(stmt, 0); client.FirstName = SQLite3.ColumnString(stmt, 1); client.LastName = SQLite3.ColumnString(stmt, 2); string date = SQLite3.ColumnString(stmt, 3); client.CreationDate = String.IsNullOrEmpty(date) ? (DateTime?)null : DateTime.Parse(date); client.Age = SQLite3.ColumnInt(stmt, 4); lstClients.Add(client); } } catch (SQLiteException ex) { Debug.WriteLine(ex.Message); } finally { // Finalize statement SQLite3.Finalize(stmt); } }
Dans une prochaine partie, nous verrons plus longuement les particularités de SQLite dans WinRT, un peu de mapping OR et quelques astuces relatives aux performances ![]()
Happy coding avec SQLite et WinRT !
-
http://www.facebook.com/willy.laroche Willy Laroche
-
Anonyme
-
http://www.facebook.com/willy.laroche Willy Laroche
-
Dams75