La pile Microsoft parle enfin la même langue

Bon, je l’avoue : en ce début d’année, je suis encore facilement impressionné par une grille qui se remplit toute seule. Pas par la couleur des lignes. Par le fait qu’on puisse partir d’une requête SQL Server, traverser ADO.NET et arriver à un contrôle visible sans raccorder trois modèles d’objets complètement différents.

Le trajet paraît court dans Visual Studio, mais les responsabilités restent séparées. SQL Server stocke les lignes et exécute la requête. Le fournisseur SqlClient traduit les appels .NET vers le protocole du serveur. Le SqlDataAdapter orchestre la lecture. Le DataSet garde une copie en mémoire. La grille observe cette copie et produit son HTML ou ses cellules Windows selon le type d’application.

Dim cn As New SqlConnection(connStr)
Dim da As New SqlDataAdapter("SELECT NoClient, Nom, Ville FROM Clients", cn)
Dim ds As New DataSet()

Try
    da.Fill(ds, "Clients")
    grdClients.DataSource = ds.Tables("Clients")
    grdClients.DataBind()
Catch ex As SqlException
    LogErreur(ex.Message)
End Try

Dans Fill, l’adapter ouvre la connexion si elle était fermée, exécute son SelectCommand, lit le résultat, crée les colonnes et les lignes du DataTable, puis referme la connexion. Le DataSet est déconnecté : il ne garde pas un curseur ouvert sur SQL Server. Cette conception convient bien à un formulaire ou à une page Web qui doit montrer et modifier des données pendant que la connexion retourne au pool.

La copie possède toutefois sa propre réalité. Si un autre utilisateur change Montréal pour Québec dans la base, ma grille ne le voit pas avant une nouvelle lecture. Chaque DataRow garde un état (Added, Modified, Deleted, Unchanged) ainsi que, pour une modification, une valeur originale et une valeur courante. Le DataAdapter.Update peut parcourir ces états et appeler une commande d’insertion, de modification ou de suppression.

Pour éviter d’écraser silencieusement le changement de quelqu’un d’autre, la commande de mise à jour peut vérifier la valeur originale :

UPDATE Clients
SET Ville = @NouvelleVille
WHERE NoClient = @NoClient
  AND Ville = @VilleOriginale

Si zéro ligne est modifiée, le client a disparu ou sa ville a changé depuis la lecture. L’application doit alors demander de recharger ou de résoudre le conflit. C’est de la concurrence optimiste : on ne garde pas un verrou pendant que la personne regarde l’écran, mais on vérifie au moment d’écrire que le point de départ est encore vrai.

Le DataSet peut aussi contenir plusieurs tables et relations, par exemple Clients et Commandes. Il peut faire respecter localement une clé ou une relation, sérialiser son contenu en XML et transmettre les changements. C’est puissant, donc très facile à surutiliser. Charger 100 000 clients alors que la grille en montre 25 consomme de la mémoire, du réseau et du temps pour rien. Une requête filtrée ou paginée vaut mieux qu’une liaison de données impressionnante.

La requête de l’exemple est fixe. Dès qu’un filtre vient de l’écran, je dois utiliser un paramètre plutôt que concaténer le nom dans le SQL. Les paramètres empêchent une apostrophe de casser la commande, conservent les types et réduisent le risque d’injection. La chaîne de connexion ne devrait pas contenir un compte administrateur; le compte de l’application a seulement les droits requis.

Les erreurs ont enfin besoin d’une frontière claire. Une panne réseau, un timeout et une violation de contrainte sont trois problèmes différents. Je peux inscrire les détails techniques dans un journal avec l’heure et l’opération, puis montrer un message plus utile que toute l’exception à la personne. Si le Fill échoue à moitié, je ne lie pas une table incomplète comme si elle était fiable.

La cohérence de la pile Microsoft me plaît, mais elle n’enlève pas les choix. Pour mon prochain écran, je vais dessiner SQL → adapter → DataSet → grille, limiter la requête au besoin réel et tester un conflit entre deux fenêtres. Si je comprends quelle copie possède quelle valeur à chaque étape, la grille qui se remplit toute seule devient autre chose qu’un truc de démo.