Utilisation de la réplication SQL dans le code .NET d'une application mobile - Implémentation & Conseils : PARTIE 1/3 (classe SqlCeReplication & première synchro)
J’ai décidé de laisser de coté mes articles “théoriques” sur la réplication de fusion avec SQL Server Compact, pour laisser un peu plus de place à la pratique.
Voyons donc maintenant comment tout cela se met en action dans le code .NET d’une application mobile !
Dans le .NET Compact Framework, c’est la classe SqlCeReplication, de l’espace de nom System.Data.SqlServerCe qui permet de prendre en charge la réplication SQL.
Dans cette première partie, nous allons voir comment s’utilisent les propriétés et les méthodes de la classe SqlCeReplication. Nous allons étudier, étape par étape, la construction d’un code C# simple pour effectuer une synchronisation de données dans une application Windows Mobile.
Utilisation de la classe SqlCeReplication :
Partons d’une simple application, qui ne comporte qu’un seul écran sur lequel nous avons placé un bouton “SYNCHRO” qui va nous permettre de lancer la synchronisation :
Pour pouvoir utiliser la réplication SQL et plus particulièrement la classe SqlCeReplication, il est d’abord nécessaire de rajouter une référence à l’assembly System.Data.SqlServerCe :
Dans le code-behind de l’unique “form”, nous allons commencer par rajouter un “using” à l’espace de nom “System.Data.SqlServerCe” :
using System.Data.SqlServerCe;
Ensuite, nous allons définir une constante qui correspond au nom de la base mobile que nous allons créer par réplication :
private const string _dbName = "DBmob.sdf";
Dans le code de l’évènement “Click” associé au bouton synchro, nous allons créer un objet “repl” de type SqlCeReplication et l’instancier à l’intérieur d’une clause “try-catch-finally”.
Le code C# ci-dessous correspond au squelette de départ de notre exemple :
using System;
using System.Data.SqlServerCe;
using System.Windows.Forms;
namespace TestReplication1
{
public partial class Form1 : Form
{
private const string _dbName = "DBmob.sdf";
public Form1()
{
InitializeComponent();
}
private void btnSynchro_Click(object sender, EventArgs e)
{
SqlCeReplication repl = null;
try
{
repl = new SqlCeReplication();
}
catch (SqlCeException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (repl != null)
repl.Dispose();
}
}
}
}
Remarque :
N’oubliez pas d’attraper les éventuelles SqlCeException dans la clause “catch” et de détruire l’objet “repl” dans la clause “finally”.
Définition des propriétés :
La classe SqlCeReplication possède de nombreuses propriétés qu’il est important de bien définir selon l’environnement utilisé (web synchro, Publisher, Distributor, etc…).
La définition de l’ensemble de ces propriétés n’est pas obligatoire et dépend entre autre du type de sécurité utilisée et de la configuration du distributor. Certaines propriétés, quant à elles, doivent obligatoirement être définies pour pouvoir effectuer une synchronisation, c’est le cas par exemple des propriétés Subscriber, Publication, InternetUrl, etc.…
Description de certaines propriétés :
-
InternetUrl: URL de l’agent de réplication exposé sur IIS.
-
InternetLogin: Login du compte utilisateur utilisé pour la connexion au répertoire virtuel IIS.
-
InternetPassword: Mot de passe du compte utilisateur utilisé pour la connexion au répertoire virtuel IIS.
-
Publisher: Nom de l’instance SQL sur laquelle tourne la base publisher.
-
PublisherSecurityMode: Type de sécurité utilisée pour la connexion à la base publisher (NT ou DB selon si la connexion à la base publisher s’effectue via un compte Windows ou un compte SQL Server).
-
PublisherLogin: Login du compte utilisé pour la connexion au publisher (dans le cas d’un type de sécurité DB).
-
PublisherPassword: Mot de passe du compte utilisé pour la connexion au publisher (dans le cas d’un type de sécurité DB).
-
PublisherDatabase: Base de données publisher à répliquer.
-
Publication: Nom de la publication à utiliser.
-
Distributor: Nom de l’instance SQL sur laquelle tourne la base de distribution (inutile de préciser dans le cas où le publisher et le distributor sont sur la même machine).
-
DistributorLogin: Login du compte utilisé pour la connexion à la base de distribution (inutile de préciser dans le cas où le publisher et le distributor sont sur la même machine).
-
DistributorPassword: Mot de passe du compte utilisé pour la connexion à la base de distribution (inutile de préciser dans le cas où le publisher et le distributor sont sur la même machine).
-
SubscriberConnectionString: Chaine de connexion à la base de données mobile répliquée.
-
Subscriber: Nom de l’abonnement.
-
HostName: valeur récupérée pour la fonction de filtrage HOST_NAME().
-
CompressionLevel: Cette propriété permet de personnaliser la compression de données. Elle peut prendre une valeur comprise entre 0 et 6. La valeur 0 désactive toute compression. La valeur par défaut est 1.
Conseil :
En spécifiant une valeur faible pour la propriété CompressionLevel, les données transmises ne seront pas fortement compressées, ce qui rallonge donc la durée de transmission. Par contre, plus la valeur est élevée, plus le temps des traitements de compression sera long sur le serveur, mais la durée de transfert sera d’autant plus courte. Il est donc question de trouver un juste milieu par rapport aux besoins. Par exemple, si le coût des données transmises est important pour le projet (forfait opérateur GPRS), il sera peut-être nécessaire d’augmenter la compression de données.
Astuce :
En ce qui concerne la chaine de connexion de l’abonnement SubscriberConnectionString, il faut savoir qu’il est possible de rajouter la clause “Max Database Size=X” afin de repousser la limite de taille définie par défaut pour les bases mobiles répliquées. En effet, par défaut la limite de taille de la base répliquée est fixée à 128Mo. Par exemple, en précisant “Max Database Size = 1000” dans la chaine de connexion, la base répliquée pourra atteindre une taille de 1Go. (La limite maximale réelle étant de 4 Go pour SQL Server Compact 3.5).
Procédure :
Juste après l’instanciation de l’objet “repl”, nous allons définir l’ensemble de ses propriétés de telle manière à pouvoir utiliser correctement une publication nommée “Pub” qui a été construite et configurée sur une base de données “BASE”.
repl = new SqlCeReplication();
repl.InternetUrl = "http://10.10.10.10/webSync/sqlcesa35.dll";
repl.InternetLogin = "login";
repl.InternetPassword = "password";
repl.Publisher = @"INSTANCE_SQL";
repl.PublisherDatabase = "BASE";
repl.PublisherSecurityMode = SecurityType.NTAuthentication;
repl.Publication = "Pub";
repl.Subscriber = "PDA1";
repl.HostName = "PDA1";
repl.SubscriberConnectionString = @"Data Source=" + _dbName
+ ";Max Database Size=1000;Default Lock Escalation =100;";
Dans l’exemple ci-dessus, nous avons donc précisé les paramètres de connexion au serveur ISS (dont l’URL de la DLL de réplication), ainsi que les paramètres du serveur de publication.
Le type de sécurité étant “NT Authentication” dans cet exemple, nous n’avons pas besoin de renseigner les propriétés PublisherLogin et PublisherPassword qui sont uniquement utilisées dans le cadre d’une authentification à l’aide d’un compte SQL Server.
Les propriétés du distributor n’ont pas non plus été précisées puisque nous considérons que le distributor et le publisher sont sur le même serveur.
La propriété HostName a été définie à “PDA1”. Pour rappel, cette valeur sera utilisée pour initialiser le système de filtres (Cf. article ici).
Astuce :
Les SDK et frameworks utilisés lors du développement d’une application mobile permettent en général de récupérer très facilement le numéro de série de l’appareil. Il peut s’avérer intéressant de créer une table “TERMINAUX”, sur la base de données serveur, qui contiendrait l’ensemble des références des terminaux portables, et qui serait utilisée pour initialiser le système de filtres.
Par exemple, en répliquant le terminal expose son numéro de série dans le “HostName”. Dès lors, le système de filtres s’applique par rapport à ce numéro de série stocké dans une table “TERMINAUX” de la base de données. Cette ligne spécifique de la table “TERMINAUX” permettra d’effectuer les jointures nécessaires avec les autres tables (utilisateurs, clients, périmètre géographique…), pour déterminer l’ensemble des données du référentiel qui doivent descendre sur ce terminal spécifique.
Méthodes et synchronisation des données :
La classe SqlCeReplication présente plusieurs méthodes importantes pour la synchronisation de données.
Description des méthodes :
-
AddSubscription : Cette méthode permet de créer l’abonnement. Cette méthode est indispensable dans le sens où l’abonnement doit obligatoirement être créé avant de pouvoir lancer la synchronisation des données. Il est possible de spécifier l’option “CreateDatabase” pour générer automatiquement la base de données mobile si elle n’existe pas.
-
DropSubscription: Cette méthode supprime l’abonnement lié à la base mobile.
-
SaveProperties: Cette méthode permet de stocker l’ensemble des propriétés définies par la classe SqlCeReplication à l’intérieur d’une table système de la base répliquée.
-
LoadProperties: Cette méthode peut être appelée suite à un “SaveProperties” pour retrouver l’ensemble des propriétés de la réplication mémorisées sur l’abonné.
-
Synchronize: C’est la méthode qui permet de lancer la synchronisation de données en mode synchrone.
-
BeginSynchronize: C’est la méthode qui permet de lancer la synchronisation de données en mode asynchrone.
Remarque & Conseils :
La méthode AddSubscription est très importante dans le sens où elle doit obligatoirement être appelée pour créer l’abonnement avant de pouvoir effectuer une synchronisation. Si la base de données mobile existe déjà, il est question de préciser l’option “ExistingDatabase”. Sinon, l’option “CreateDatabase” permettra de générer automatiquement la base de données par réplication, au chemin spécifié par la chaine de connexion SubscriberConnectionString.
La méthode LoadProperties est utile par exemple dans le cas où une base mobile serait générée par réplication en dehors de l’application mobile, et copiée sur l’appareil. Dans ce cas, il suffit de faire appel à LoadProperties, dans le code de l’application mobile, pour rappeler facilement l’ensemble des propriétés définies. Suite à un LoadProperties, la méthode AddSubscription n’a plus besoin d’être appelée. Seules certaines propriétés comme les mots de passe, ou le HOST_NAME ne sont pas sauvegardées et doivent de nouveau être précisées juste avant de lancer la synchronisation.
Procédure :
Maintenant que nous avons défini l’ensemble des propriétés nécessaires, nous allons rajouter l’abonnement sur la base en spécifiant que la base mobile doit être générée entièrement par réplication.
Pour ce faire, nous allons faire appel à la méthode AddSubscription et préciser l’option CreateDatabase pour créer entièrement la base par réplication :
repl.AddSubscription(AddOption.CreateDatabase);
La création de la base mobile et l’ajout de l’abonnement ne sont valables uniquement lors de la première synchro. En effet, pour les synchronisations suivantes, la base sera déjà créée et l’abonnement sera déjà présent sur la base. C’est pourquoi, il est intelligent de tester au préalablement l’existence de la base de données pour effectuer l’ajout de l’abonnement avec l’option CreateDatabase :
if (!System.IO.File.Exists(_dbName))
repl.AddSubscription(AddOption.CreateDatabase);
Suite à l’ajout de l’abonnement, nous pouvons enfin appeler la méthode Synchronize qui permet de lancer la synchronisation. Voici à quoi ressemble à présent l’ensemble du code de la “form” :
using System;
using System.Data.SqlServerCe;
using System.Windows.Forms;
namespace TestReplication1
{
public partial class Form1 : Form
{
private const string _dbName = "DBmob.sdf";
public Form1()
{
InitializeComponent();
}
private void btnSynchro_Click(object sender, EventArgs e)
{
SqlCeReplication repl = null;
try
{
repl = new SqlCeReplication();
repl.InternetUrl = "http://10.10.10.10/webSync/sqlcesa35.dll";
repl.InternetLogin = "login";
repl.InternetPassword = "password";
repl.Publisher = @"INSTANCE_SQL";
repl.PublisherDatabase = "BASE";
repl.PublisherSecurityMode = SecurityType.NTAuthentication;
repl.Publication = "Pub";
repl.Subscriber = "PDA1";
repl.HostName = "PDA1";
repl.SubscriberConnectionString = @"Data Source=" + _dbName
+ ";Max Database Size=1000;Default Lock Escalation =100;";
if (!System.IO.File.Exists(_dbName))
repl.AddSubscription(AddOption.CreateDatabase);
repl.Synchronize();
}
catch (SqlCeException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (repl != null)
repl.Dispose();
}
}
}
}
Il s’agit bien entendu d’un exemple simple qui permet de comprendre au mieux comment faire appel à la réplication SQL dans une application mobile.
Le code de la réplication doit être modulé selon les projets. Il n’est surtout pas question de reprendre le code C# tel qu’il est présenté ci-dessus, mais plutôt de l’adapter à votre architecture et en fonction de vos besoins.
A suivre…
Pi-R.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :