Tables jointes Si vous devez lire des données provenant simultanément de deux tables, vous pouvez toujours appeler une commande SQL avec une jointure. Le résultat est cependant une table unique, contenant des champs provenant de plusieurs tables différentes. C’est très fonctionnel dans le cas où vous vous contentez d’afficher les données, mais si vous permettez les modifications et voulez éventuellement effectuer une mise à jour dans la base de données, les choses deviennent plus compliquées. Il devient en effet plus difficile de s’assurer que les règles d’intégrité entre les tables sont respectées. Il est aussi possible que certaines informations soient manquantes. Il y a peut-être un sujet « Architecture » dans la table de sujets. Si aucune photo n’est cataloguée dans ce sujet, il ne fera pas partie du résultat de la requête et vous n’aurez aucune façon de savoir que ce sujet existe. Vous perdez l’accès à certains mécanismes qui permettent d’automatiser les mises à jour, qui ne fonctionnent que quand la commande de sélection est appelée sur une table unique. Il est donc souvent plus intéressant de remplacer la requête avec jointure par des requêtes individuelles sur chacune des tables, et de recréer en mémoire les relations liant les tables. Vous pouvez le faire avec une commande SQL pour chaque table et plusieurs Fill successifs sur le même DataSet, ce qui ajoutera une table à chaque appel : dad.SelectCommand = comTblSujet dad.Fill(dts, "Sujets") dad.SelectCommand = comTblPhoto dad.Fill(dts, "Photos") Le DataSet dts contient maintenant une Tables(0) appelée Sujets et une Tables(1) appelée Photos. Access vous limite à cette approche, mais les bases de données permettant de créer des procédures plus complexes permettent de faire le même travail en une seule procédure. Cette approche n’est pas utilisée dans l’application d’exemples, mais voici le code qui récupérerait les tables de photos et de sujets et les lierait ensemble. Nous créerions tout d’abord dans la base de données une procédure stockée appelant séparément les deux tables : CREATE PROCEDURE psPhotosSujet (@Doss varchar(255)) AS SELECT FROM tbSujets.* tbSujets SELECT FROM WHERE * tbPhotos (Dossier = @Doss) GO Vous constaterez que quand vous appelez une procédure stockée contenant plusieurs commandes SELECT, le DataAdapter crée automatiquement une table individuelle pour chacune des commandes. Les plus vieux d’entre vous s’exclameront probablement : « cool ». Les plus jeunes diront plutôt « full au boutte ». Dim Dim Dim Dim Dim Dim con As New SqlConnection(pcConnectionString) com As New SqlCommand dad As SqlDataAdapter dts As DataSet tbPhoto As DataTable tbSujet As DataTable com.CommandText = "EXEC psPhotosSujet 'C:\Cours ADONET\PhotoCatBD\Images'" com.Connection = con dad = New SqlDataAdapter(com) dts = New DataSet Try dad.FillSchema(dts, SchemaType.Source) Catch ex As SqlException Stop End Try tbSujet = dts.Tables(0) tbPhoto = dts.Tables(1) tbSujet.PrimaryKey = New DataColumn() {tbSujet.Columns("NoSujet")} dts.Relations.Add(New DataRelation("FK_tbSujet_tbPhoto", _ tbSujet.Columns("NoSujet"), tbPhoto.Columns("NoSujet"))) dad.Fill(dts) À partir de ce point, vous êtes protégé comme si vous tentiez d’écrire dans la base de données. Vous devrez ajouter un sujet inexistant avant de pouvoir l’assigner à une photo, et ne pourrez détruire par inadvertence un sujet pour lequel vous avez des photos. Si, comme dans notre exemple, vous créez la relation avant de faire le Fill, il est important que la procédure récupère la table de sujets avant la table de photos, sinon vous aurez une erreur parce que les photos importées référencent des sujets non existant. Les règles sont en effet actives pendant le Fill. De même, lors de la mise à jour de la base de données, assurez-vous d’enregistrer les ajouts faits à la table de sujets avant ceux de la table de photos, pour éviter que les règles d’intégrités de la BD ne rejettent les photos référençant les nouveaux sujets.