Exporter (0) Imprimer
Développer tout
1 sur 1 ont trouvé cela utile - Évaluez ce sujet

Développement de bases de données pour Pocket PC Phone Edition sous Windows

Andy Sjostrom
businessanyplace

S'applique à :
Pocket PC Phone Edition

Résumé : Apprenez à utiliser les outils Pocket PC Phone Edition pour construire rapidement des applications sans fil. Cet article va vous aider à réaliser une application Pocket PC Phone Edition à l'aide de Visual C# et SQL Server CE 2.0. Si vous ne connaissez pas le .NET Compact Framework, nous vous recommandons de consulter le Livre Blanc .NET Compact Framework Overview ( Quitter le site MSDN France Site en anglais).

Sommaire

Une nouvelle ère commence pour l'informatique mobile
Nouveautés de SQL Server CE
L'exemple d'application : d'un bout à l'autre du green
L'exemple d'application : d'un bout à l'autre du code
Trucs et astuces
Conclusion
Pour plus d'informations

Une nouvelle ère commence pour l'informatique mobile

Les éléments de l'architecture du système de solution mobile se sont rapidement mises en place. Tout d'abord, les entreprises prennent de plus en plus conscience du surplus d'efficacité et des opportunités commerciales que représentent les solutions mobiles. Les consommateurs commencent également à comprendre l'utilité des équipements mobiles dans leur vie quotidienne. Ces équipements mobiles et, en particulier les nouveaux Pocket PC, sont à la tête de cette évolution et peuvent combler les besoins des entreprises tout comme ceux des consommateurs. Désormais, l'innovation logicielle va de pair avec les outils de développement.

Ces derniers mois, j'ai travaillé avec les nouvelles versions de Visual Studio .NET, Smart Device Extensions et SQL Server™ CE 2.0. Ces composants logiciels, combinés aux Pocket PC connectés, tels que le Pocket PC Phone Edition, améliorent l'efficacité du développement et sont déjà utilisés par de nombreuses applications mobiles.

Nouveautés de SQL Server CE

Vu dans son ensemble, SQL Server CE dévoile un paradoxe. En tant que base de données locale pour équipements mobiles, SQL Server CE prend en charge les scénarios déconnectés. Dans la plupart des cas, une application Pocket PC en cours d'exécution sur un Pocket PC non connecté à un réseau nécessitera un stockage local des données. SQL Server CE prend également en charge les scénarios connectés et augmente l'efficacité du transfert de données en direction et depuis des serveurs distants, du point de vue du développement et de la bande passante.

Voici quelques-unes des caractéristiques notables de SQL Server CE :

  • Intégration avec les classes du .NET Compact Framework pour la gestion locale de SQL Server CE et pour la connectivité à SQL Server distant
  • Simplification de l'installation des composants SQL Server CE grâce à des assistants d'établissement de la connectivité
  • Grand nombre de fonctions intrinsèques, parmi lesquelles les très appréciées NEWID, CHAR, CHARINDEX, UNICODE, LEN, LTRIM, RTRIM, SPACE, SUBSTRING, IDENTITY et DATALENGTH
  • UNION (SELECT * FROM Orders UNION SELECT * FROM OldOrders)
  • Possibilité d'extraction des index de table du serveur distant à l'aide de la fonction Remote Data Access Pull
  • Amélioration notable de SQL Server Query Analyzer

La nouvelle architecture d'accès aux données SQL Server CE 2.0 se base sur les classes trouvées dans les espaces de noms :

  • System.Data.SqlServerCE (gère la connectivité de la base de données locale et du serveur distant à l'aide des classes Merge Replication et Remote Data Access)
  • System.Data.SqlClient (gère les bases de données distantes et inclue la prise en charge de TSQL et des procédures mémorisées)

Étant donnée que l'architecture d'accès aux données a été transférée vers le .NET Compact Framework, les composants inclus ont été améliorés et sont plus faciles à utiliser. Par exemple, la précédente version du schéma Merge Replication Initialize, Run et Terminate a été remplacée par une méthode unique, System.Data.SQLServerCE.Replication.Synchronize, qui permet de créer le schéma et de télécharger les données lors de la première synchronisation. Les données modifiées sont ensuite transférées et de nouveaux téléchargées lors des synchronisations ultérieures.

Les nouvelles classes Remote Data Access offrent aussi des améliorations, dont la capacité à retirer des index de tables distants et la capacité à définir un mode batch pour la méthode Push. Je vais maintenant vous guider à travers la conception d'un exemple d'application de fiche de score de golf, à l'aide de SQL Server CE 2.0, Remote Data Access et Visual C#, puis nous jetterons un coup d'œil au code.

L'exemple d'application : d'un bout à l'autre du green

L'exemple d'application Golf Anyplace peut être exécuté sur les Pocket PC standards. Toutefois, la connectivité intégrée du Pocket PC Phone Edition représentera un grand avantage sur un véritable terrain de golf. Golf Anyplace est en fait une fiche de score numérique, capable de tenir le compte de vos résultats et des résultats d'autres joueurs. L'idée est que tous les golfeurs concernés utilisent Pocket PC Phone Edition afin de tenir à jour leur score. Tous les joueurs envoient leurs scores au serveur distant et peuvent récupérer ceux des autres joueurs, ce qui permet ainsi de suivre l'avancée de la partie en temps réel.

Voici à quoi ressemble l'interface (je sais, je ne suis pas concepteur d'interface) :

Le formulaire principal est utilisé pour entrer votre propre score. Il peut également servir à visualiser le score des autres joueurs.

Entrez votre score

Figure 1. Entrez votre score

La commande Synchronize envoie les données locales au serveur distant, puis récupère toutes les données distantes.

Synchronisez les scores

Figure 2. Synchronisez les scores

Vous pouvez utiliser le formulaire View pour avoir à la fois une vue détaillée et générale de la partie

Consultez les scores des autres golfeurs

Figure 3. Consultez les scores des autres golfeurs

L'exemple d'application : d'un bout à l'autre du code

Examinons le code. En certains endroits du code, vous remarquerez que j'ai choisi de résoudre des problèmes identiques de différentes manières. Certains exemples montrent comment je m'y prends pour initialiser les classes à l'aide de DataReader vs DataSet, pour remplir une ListView à l'aide de SQL Server CE wrapper ou non, etc. J'espère que cette démonstration vous sera utile, car il faut garder à l'esprit qu'une solution peut être parfaitement adaptée à un scénario donné, tandis qu'une autre solution sera plus efficace avec un autre scénario. Notez que vous pouvez télécharger le code de l'exemple Golf Anyplace.

Démarrage

L'objet de démarrage de Golf Anyplace est GolfAnyplace.RDAGolf. Voici la logique du constructeur au démarrage de l'application :

public RDAGolf()
{
InitializeComponent();

// Assurez-vous qu'il existe une base de données !
SQLServerCEWrapper SSCEWrapper = new SQLServerCEWrapper();
bool NewDatabase = SSCEWrapper.CreateDatabase();

// Si une nouvelle base de données a été créée, effectuer un premier téléchargement !
if(NewDatabase==true)
{
// Appeler le téléchargement sans conserver les données locales ! (rien ici !)
SSCEWrapper.Pull(false);
}

// Remplir la liste modifiable.
for(int iCounter=1; iCounter < 19; iCounter++)
this.cmbHole.Items.Add(iCounter.ToString());

// Définir le premier emplacement comme emplacement par défaut.
this.cmbHole.SelectedIndex = 0;

}

Vous pouvez constater que j'ai implémenté un wrapper SQL Server CE. J'ai procédé ainsi pour structurer le code lié à la base de données en un endroit. Le wrapper m'aide à gérer et travailler avec les bases de données locales, ainsi qu'à gérer la synchronisation du serveur distant.

Cet extrait montre les premières lignes de code du wrapper.

using System;
using System.Data;
using System.Windows.Forms;
using System.Collections;
using System.Data.Common;
using System.Data.SqlServerCe;
using System.Data.SqlClient;

namespace GolfAnyplace
{

public class SQLServerCEWrapper
{

public string InternetServer = "http://servername/directory/sscesa20.dll";
public string InternetUser ="DOMAIN\\user";
public string InternetPassword = "password";
public string RemoteConnection = "Provider=sqloledb;Data Source=MySQLServer;Initial Catalog=GolfAnyplace;User Id=user;Password=password";
public string LocalDatabase = "\\My Documents\\ga.sdf";
public string LocalConnection = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\\My Documents\\ga.sdf";
public string LocalTableName = "Result";
public string RemoteTableName = "Result";

La seule raison pour laquelle j'ai rendu publiques les propriétés RDA est que j'en aurai besoin pour illustrer l'utilisation du DataReader dans un autre endroit de l'application. Les propriétés RDA devraient en réalité rester confidentielles et, pour faire preuve de cohérence avec le reste de l'application, je devrais, au lieu de les divulguer, faire passer un DataSet depuis le wrapper.

Voici à quoi ressemble les méthodes CreateDatabase et Pull du wrapper :

public bool CreateDatabase()
{
// Assurez-vous que la base de données existe bien.
// Choisir Return true si une nouvelle base de données a été créée.
// Choisir Return false si aucune nouvelle base de données n'a été créée.
// Bogues identifiés :
// Version Date Auteur Commentaire
// 00.00.000 020808 ASJ Créé
// *****************************

if(System.IO.File.Exists(LocalDatabase) == false)
{
System.Data.SqlServerCe.Engine SQLCEEngine = new System.Data.SqlServerCe.Engine(LocalConnection);
SQLCEEngine.CreateDatabase();
return true;
}
else
{
return false;
}

La méthode CreateDatabase crée une nouvelle base de données, s'il n'en existe pas.

public void Pull(bool KeepLocalData)
{
// Télécharger la table dans la base de données locale.
// Bogues identifiés :
// Version Date Auteur Commentaire
// 00.00.000 020808 ASJ Créé
// *****************************
string SQL;
SqlCeConnection cn;
SqlCeCommand cmd;
RemoteDataAccess RDA = null;

// Créer et initier le nouvel objet RDA.
RDA = new RemoteDataAccess(InternetServer, InternetUser, InternetPassword, LocalConnection);

// Conserver les données locales ? Si oui, les transférer sur le serveur en priorité !
if(KeepLocalData)
{
RDA.Push(LocalTableName, RemoteConnection, RdaBatchOption.BatchingOff);
}

// Avant la commande Pull, nous devons supprimer la table locale.
// Ouvrez la connexion à la base de données locale.
cn = new SqlCeConnection(LocalConnection);
cn.Open();

// Supprimer la table locale.
SQL = "DROP TABLE " + LocalTableName;
cmd = new SqlCeCommand(SQL, cn);

// Une erreur se produit si la table n'existe pas.
// Si cela se produit, je veux tout de même continuer.
try
{
cmd.ExecuteNonQuery();
}
catch{ }

// Fermer la connexion.
cn.Dispose();

// Enfin, il est temps de télécharger la table distante !
SQL = "SELECT PlayerName, Hole, Result FROM " + RemoteTableName;
RDA.Pull(LocalTableName, SQL, RemoteConnection, RdaTrackOption.TrackingOnWithIndexes, "RDAErrors");

// Nettoyer.
RDA.Dispose();

}

Notez que je passe une variable booléenne dans la méthode Pull. Il est impossible de transférer du contenu depuis une table de serveur distante vers une table de SQL Server CE locale déjà existante. Le transfert doit donc être précédé d'une instruction DROP TABLE. La variable booléenne sert à contrôler s'il faut ou non conserver les données locales lors du premier transfert au serveur. Vous pouvez aussi consulter les nouveaux paramètres de batching sur la méthode Push. Dans ce cas j'utilise BatchingOff, qui signifie que je ne considère pas les lignes envoyées au serveur comme un batch, à transmettre intégralement ou pas du tout. L'autre réglage valide est BatchingOn. Comme vous le voyez, j'utilise la commande SqlCeCommand pour exécuter l'instruction DROP TABLE.

J'aimerais ici souligner le fait que je spécifie les noms de champ dans l'instruction Pull. Assurez-vous de toujours bien spécifier les noms de champ, à la fois dans les instructions Pull et dans les instructions normales SELECT. Ainsi, vous aurez la garantie de modifier uniquement les données qui doivent absolument être modifiées. De plus, vous pouvez facilement éviter les problèmes liés au fait que certains champs ne sont pas téléchargeables, tels que les champs rowguidcol, int identity et timestamp.

Qu'est-ce qui se trouve sur le serveur ?

Avant d'aller plus loin dans le code source de l'application Pocket PC, j'aimerais révéler ce qui se trouve coté serveur. Le serveur distant est un SQL Server 2000 qui gère une base de données nommée GolfAnyplace. La base de données ne comporte qu'une seule table, la table Result. Voici la définition des données de la table :

CREATE TABLE [dbo].[Result] (
[PlayerName] [nvarchar] (50) NOT NULL ,
[Hole] [smallint] NOT NULL ,
[Result] [smallint] NOT NULL 
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Result] WITH NOCHECK ADD 
CONSTRAINT [PK_Result] PRIMARY KEY CLUSTERED 
(
[PlayerName],
[Hole],
[Result]
) ON [PRIMARY]

J'ai également configuré l'agent du serveur SQL Server CE 2.0 avec l'aide bien pratique de certains Assistants.

Remplissage d'une liste

Le projet GolfAnyplace illustre deux manières de remplir une liste affichée : en utilisant un DataSet et en utilisant un DataReader. Étant donné que j'ai choisi d'implémenter un wrapper autour de SQL Server CE, il est plus logique d'utiliser un DataSet. Un DataSet peut être déconnecté et échangé (ordonné) entre les classes de cet état déconnecté. Étant donné qu'un DataReader requiert une connexion ouverte à la base de données, son utilisation devrait être aussi proche que possible de l'ouverture et de la fermeture de la connexion. Le premier extrait de code montre comment remplir une liste en opérant une boucle dans un DataSet.

Voici le code qui sert à remplir la liste affichée :

private void UpdateResultListView()
{
// Mise à jour de la liste
// Bogues identifiés :
// Version Date Auteur Commentaire
// 00.00.000 020808 ASJ Créé
// *****************************
DataSet ds = null;
SQLServerCEWrapper SSCEWrapper = new SQLServerCEWrapper();

// Récupérer le DataSet.
ds = SSCEWrapper.GetPlayerResult(txtPlayerName.Text);

// Supprimer la liste.
lvwResult.Items.Clear();

// Effectuer une boucle dans le DataSet.
foreach (DataRow dr in ds.Tables[0].Rows)
{
ListViewItem lviItem = new ListViewItem(dr["Hole"].ToString());
lviItem.SubItems.Add(dr["Result"].ToString());
lvwResult.Items.Add(lviItem);
}
}

Voici le code correspondant trouvé dans la classe wrapper :

public DataSet GetPlayerResult(string PlayerName)
{
// Récupérer les données de la base de données locale. Les renvoyer en tant que DataSet.
// Bogues identifiés :
// Version Date Auteur Commentaire
// 00.00.000 020808 ASJ Créé
// *****************************
string SQL;
SqlCeConnection cn;
SqlCeCommand cmd;
DataSet ds;
SqlCeDataAdapter da;

// Initialiser une nouvelle connexion.
cn = new SqlCeConnection(LocalConnection);

// Ouvrir la connexion.
cn.Open();

// Construire SQL.
SQL = "SELECT PlayerName, Hole, Result FROM " + LocalTableName + " WHERE PlayerName = '" + PlayerName + "' ORDER BY Hole";

// Initialiser une nouvelle commande.
cmd = new SqlCeCommand(SQL,cn);

// Initialiser un nouveau DataSet
ds = new DataSet();
da = new SqlCeDataAdapter(SQL,cn);

// Remplir le DataSet avec des données à l'aide de l'adaptateur.
da.Fill(ds, LocalTableName);

// Effectuer un nettoyage.
cn.Dispose();
cmd.Dispose(true);

// Renvoyer le DataSet.
return ds;

}

L'extrait de code suivant montre comment réaliser la même chose en utilisant cette fois DataReader.

private void UpdateDetailedResultListView()
{
// Mettre à jour les résultats détaillés à l'aide d'un DataReader.
// Bogues identifiés :
// Version Date Auteur Commentaire
// 00.00.000 020808 ASJ Créé
// *****************************
SQLServerCEWrapper SSCEWrapper = new SQLServerCEWrapper();
string SQL;

// SQL pour la liste détaillée !
SQL = "SELECT PlayerName, Hole, Result FROM Result ORDER BY PlayerName, Hole";

SqlCeConnection cn = new SqlCeConnection();
cn.ConnectionString = SSCEWrapper.LocalConnection;

// Ouvrir la connexion.
cn.Open();

// Initialiser la commande et l'exécuter vers le lecteur.
SqlCeCommand cmd = new SqlCeCommand(SQL,cn);
SqlCeDataReader dtr = cmd.ExecuteReader();

// Supprimer la liste.
this.lvwResultDetailed.Items.Clear();

// Commencer la lecture !
while (dtr.Read())
{

ListViewItem lviItem = new ListViewItem(dtr["PlayerName"].ToString());
lviItem.SubItems.Add(dtr["Hole"].ToString());
lviItem.SubItems.Add(dtr["Result"].ToString());
lvwResultDetailed.Items.Add(lviItem);

}

// Fermer le DataReader.
dtr.Close();

// Effectuer un nettoyage.
cmd.Dispose(true);
cn.Dispose();

}

Enfin, notez que l'extrait de code à télécharger peut utiliser la gestion des erreurs. J'ai aussi laissé le formulaire Options (voir figure 4) dans le projet bien que celui-ci nécessite du code supplémentaire pour une prise en charge complète.

formulaire d'Options SQL Server CE

Figure 4. formulaire d'Options SQL Server CE

Trucs et astuces

Il existe des trucs et astuces dont j'aimerais vous faire profiter :

  • Faites appel à un concepteur d'interface utilisateur.
  • Assurez toujours à votre code SQL Server CE une gestion convenable des erreurs à l'aide des constructions Try, Catch et Finally.
  • Vous pouvez utiliser Pocket Emulator si vous n'avez pas de Pocket PC conçu pour le développement ou un adaptateur Ethernet conçu pour votre Pocket PC.
  • Fiez-vous aux Assistants de connectivité de SQL Server CE, ou commencez au moins par les utiliser.
  • Utilisez SQL Profiler côté serveur pour contrôler ce qui se passe lors des téléchargements et transferts de données vers le serveur, ou utilisez la fonction Merge Replication. Cela vous permettra au moins de surveiller tout ce qui se passe.
  • Sachez où trouver les réponses à vos problèmes de codage sur Internet. Vous trouverez plus bas quelques-uns de mes sites préférés.

Conclusion

Visual Studio .NET, Visual C# ou Visual Basic .NET et SQL Server CE 2.0 sont parfaitement compatibles entre eux. J'espère que vous parviendrez à trouver d'autres bonnes idées à partir de ce que je vous ai expliqué dans cet article.

Pour plus d'informations ( Quitter le site MSDN France Site en anglais)



Dernière mise à jour le jeudi 10 avril 2003



Pour en savoir plus
Cela vous a-t-il été utile ?
(1500 caractères restants)
Merci pour vos suggestions.
Afficher:
© 2014 Microsoft. Tous droits réservés.