TripPin, partie 4 - Chemins d’accès à la source de données
Ce tutoriel en plusieurs parties traite de la création d’une extension de source de données pour Power Query. Le tutoriel est destiné à être utilisé de manière séquentielle : chaque leçon s’appuie sur le connecteur créé dans les leçons précédentes, ajoutant de nouvelles fonctionnalités de manière incrémentielle.
Dans cette leçon, vous allez :
- Simplifier la logique de connexion pour votre connecteur
- Améliorer l’expérience de table de navigation
Cette leçon simplifie le connecteur créé à la leçon précédente en supprimant ses paramètres de fonction obligatoires et en améliorant l’expérience utilisateur grâce au passage à une table de navigation générée de façon dynamique.
Pour une explication détaillée de la façon dont les informations d’identification sont identifiées, consultez la section Chemins d’accès à la source de données dans Gestion de l’authentification.
Chemins d’accès à la source de données
Lors de l’appel d’une fonction de source de données, le moteur M détermine les informations d’identification à utiliser lors d’une évaluation en effectuant une recherche basée sur les valeurs Type de source de données et Chemin d’accès à la source de données.
Dans la leçon précédente, vous avez partagé deux fonctions de source de données, chacune avec un seul paramètre Uri.Type.
[DataSource.Kind="TripPin"]
shared TripPin.Feed = Value.ReplaceType(TripPinImpl, type function (url as Uri.Type) as any);
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = Value.ReplaceType(TripPinNavTable, type function (url as Uri.Type) as any);
Lors de la première exécution d’une requête utilisant l’une des fonctions, vous recevez une invite de demande d’informations d’identification avec des listes déroulantes vous permettant de sélectionner un chemin d’accès et un type d’authentification.
Ensuite, si vous réexécutez la même requête avec les mêmes paramètres, le moteur M est en mesure de localiser les informations d’identification mises en cache et aucune invite de demande d’informations d’identification ne s’affiche. Si vous modifiez l’argument url
pour votre fonction de sorte que le chemin de base ne correspond plus, une nouvelle invite de demande d’informations d’identification s’affiche pour le nouveau chemin d’accès.
Vous pouvez voir toutes les informations d’identification mises en cache dans la table Informations d’identification dans la fenêtre Sortie de requête M.
Selon le type de modification, le changement des paramètres de votre fonction entraînera probablement une erreur d’informations d’identification.
Simplification du connecteur
Vous allez maintenant simplifier votre connecteur en supprimant les paramètres de votre fonction de source de données (TripPin.Contents
). Vous allez également supprimer le qualificateur shared
pour TripPin.Feed
, et le conserver en tant que fonction interne uniquement.
L’une des philosophies de conception de Power Query est de garder le dialogue initial de la source de données aussi simple que possible. Si possible, vous devriez fournir à l’utilisateur des choix au niveau du Navigateur, plutôt que dans la boîte de dialogue de connexion. Si une valeur fournie par l’utilisateur peut être déterminée par programme, envisagez de l’ajouter comme niveau supérieur de votre table de navigation plutôt qu’un paramètre de fonction.
Par exemple, lors de la connexion à une base de données relationnelle, vous pourriez avoir besoin de noms de serveur, de base de données et de table.
Une fois que vous connaissez le serveur auquel vous connecter et que les informations d’identification ont été fournies, vous pouvez utiliser l’API de la base de données pour extraire une liste de bases de données et une liste de tables contenues dans chaque base de données.
Dans ce cas, pour que votre boîte de dialogue de connexion initiale reste aussi simple que possible, seul le nom du serveur devrait être un paramètre obligatoire, tandis que Database
et Table
seraient des niveaux de votre table de navigation.
Étant donné que le service TripPin a un point de terminaison d’URL fixe, vous n’avez pas besoin d’inviter l’utilisateur à entrer des valeurs. Vous allez supprimer le paramètre url de votre fonction, et définir une variable BaseUrl dans votre connecteur.
BaseUrl = "https://services.odata.org/v4/TripPinService/";
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;
Vous conserverez la fonction TripPin.Feed
, mais ne la partagerez plus, ne l’associerez plus à un type de source de données, et simplifierez sa déclaration. Ensuite, vous ne l’utiliserez qu’en interne dans ce document de section.
TripPin.Feed = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Si vous mettez à jour l’appel TripPin.Contents()
dans votre fichier TripPin.query.pq
et l’exécutez dans Visual Studio Code, une nouvelle invite de demande d’informations d’identification s’affiche. Notez qu’il existe maintenant une seule valeur de Chemin d’accès à la source de données : TripPin.
Amélioration de la table de navigation
Dans le premier tutoriel, vous avez utilisé les fonctions intégrées OData
pour la connexion au service TripPin.
Vous obtenez ainsi une table de navigation esthétique, basée sur le document de service TripPin, sans code supplémentaire de votre côté.
La fonction OData.Feed a automatiquement accompli le gros du travail à votre place.
Comme vous ébauchez à l’aide de Web.Contents plutôt qu’OData.Feed, vous allez devoir recréer vous-même cette table de navigation.
Vous allez apporter les modifications suivantes :
- Définir une liste d’éléments à afficher dans votre table de navigation
- Supprimer les fonctions spécifiques de l’entité (
GetAirlineTables
etGetAirportsTable
)
Génération d’une table de navigation à partir d’une liste
Vous allez répertorier les entités que vous souhaitez exposer dans la table de navigation et générer l’URL appropriée pour y accéder. Étant donné que toutes les entités figurent dans le même chemin racine, vous pourrez générer ces URL de manière dynamique.
Pour simplifier l’exemple, vous n’allez exposer que les trois ensembles d’entités (Airlines, Airports, People) qui seraient exposés sous forme de Tables dans M, et ignorer le singleton (Me) qui serait exposé en tant qu’enregistrement. Vous allez ignorer l’ajout des fonctions jusqu’à une leçon ultérieure.
RootEntities = {
"Airlines",
"Airports",
"People"
};
Ensuite, vous mettez ensuite à jour votre fonction TripPinNavTable
pour générer la table une colonne à la fois.
La colonne [Data] pour chaque entité est récupérée en appelant TripPin.Feed
avec l’URL complète de l’entité.
TripPinNavTable = (url as text) as table =>
let
entitiesAsTable = Table.FromList(RootEntities, Splitter.SplitByNothing()),
rename = Table.RenameColumns(entitiesAsTable, {{"Column1", "Name"}}),
// Add Data as a calculated column
withData = Table.AddColumn(rename, "Data", each TripPin.Feed(Uri.Combine(url, [Name])), Uri.Type),
// Add ItemKind and ItemName as fixed text values
withItemKind = Table.AddColumn(withData, "ItemKind", each "Table", type text),
withItemName = Table.AddColumn(withItemKind, "ItemName", each "Table", type text),
// Indicate that the node should not be expandable
withIsLeaf = Table.AddColumn(withItemName, "IsLeaf", each true, type logical),
// Generate the nav table
navTable = Table.ToNavigationTable(withIsLeaf, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
in
navTable;
Lorsque vous créez des chemins d’URL de façon dynamique, assurez-vous que vous êtes bien à l’emplacement où se trouvent vos barres obliques (/). Notez que Uri.Combine utilise les règles suivantes lors de la combinaison de chemins :
- Lorsque le paramètre
relativeUri
commence par une barre oblique (/), il remplace l’intégralité du chemin d’accès du paramètrebaseUri
- Si le paramètre
relativeUri
ne commence pas par une barre oblique (/) et quebaseUri
se termine par une barre oblique (/), le chemin d’accès est ajouté - Si le paramètre
relativeUri
ne commence pas par une barre oblique (/) et quebaseUri
ne se termine pas par une barre oblique (/), le dernier segment du chemin d’accès est remplacé
L’image suivante illustre cela :
Supprimer les fonctions spécifiques de l’entité
Pour faciliter la maintenance de votre connecteur, vous allez supprimer les fonctions de mise en forme spécifiques de l’entité, que vous avez utilisées dans la leçon précédente (GetAirlineTables
et GetAirportsTable
).
Au lieu de cela, vous allez mettre à jour TripPin.Feed
pour traiter la réponse JSON d’une manière qui fonctionnera pour toutes vos entités.
Plus précisément, vous prenez le champ value
de la charge utile JSON OData retournée, et le convertissez de liste d’enregistrements en table.
TripPin.Feed = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source),
// The response is a JSON record - the data we want is a list of records in the "value" field
value = json[value],
asTable = Table.FromList(value, Splitter.SplitByNothing()),
// expand all columns from the record
fields = Record.FieldNames(Table.FirstValue(asTable, [Empty = null])),
expandAll = Table.ExpandRecordColumn(asTable, "Column1", fields)
in
expandAll;
Remarque
Un inconvénient de l’utilisation d’une approche générique pour traiter vos entités est que vous perdez les informations de formatage et de type de vos entités. Une section ultérieure de ce tutoriel montre comment appliquer un schéma aux appels d’API REST.
Conclusion
Dans ce tutoriel, vous avez nettoyé et simplifié votre connecteur en corrigeant la valeur de votre Chemin d’accès à la source de données, et en passant à un format plus flexible pour votre table de navigation. Après que vous avez suivi ces étapes (ou utilisé l’exemple de code figurant dans ce répertoire), la fonction TripPin.Contents
retourne une table de navigation dans Power BI Desktop.