TripPin Teil 4 - Datenquellenpfade
Dieser mehrteilige Lehrgang behandelt die Erstellung einer neuen Datenquellenerweiterung für Power Query. Der Lehrgang sollte nacheinander durchgeführt werden - jede Lektion baut auf dem in den vorangegangenen Lektionen erstellten Connector auf und fügt dem Connector schrittweise neue Funktionen hinzu.
In dieser Lektion lernen Sie Folgendes:
- Vereinfachen Sie die Verbindungslogik für Ihren Connector
- Verbessern Sie das Erlebnis der Navigationstabelle
In dieser Lektion wird der in der vorangegangenen Lektion erstellte Connector vereinfacht, indem die erforderlichen Funktionsparameter entfernt werden und die Benutzerfreundlichkeit durch den Wechsel zu einer dynamisch generierten Navigationstabelle verbessert wird.
Eine ausführliche Erklärung, wie Anmeldeinformationen identifiziert werden, finden Sie im Abschnitt Datenquellenpfade von Handhabung der Authentifizierung.
Pfade zu den Datenquellen
Wenn eine Datenquellenfunktionaufgerufen wird, identifiziert die M-Engine, welche Anmeldeinformationen während einer Auswertung zu verwenden sind, indem sie auf der Grundlage der Werte Datenquellenart und Datenquellenpfad eine Suche durchführt.
In der vorherigen Lektion haben Sie zwei Datenquellenfunktionen gemeinsam genutzt, beide mit einem einzigen Parameter 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);
Wenn Sie zum ersten Mal eine Abfrage ausführen, die eine der Funktionen verwendet, erhalten Sie eine Eingabeaufforderung mit Dropdown-Listen, aus denen Sie einen Pfad und einen Authentifizierungstyp auswählen können.
Wenn Sie dieselbe Abfrage mit denselben Parametern erneut ausführen, kann die M-Engine die zwischengespeicherten Anmeldedaten finden, und es wird keine Eingabeaufforderung für die Anmeldedaten angezeigt. Wenn Sie das Argument url
in Ihrer Funktion so ändern, dass der Basispfad nicht mehr übereinstimmt, wird eine neue Eingabeaufforderung für den neuen Pfad angezeigt.
Sie können alle zwischengespeicherten Anmeldeinformationen in der Tabelle Anmeldeinformationen im Fenster M Query Output sehen.
Je nach Art der Änderung führt die Änderung der Parameter Ihrer Funktion wahrscheinlich zu einem Berechtigungsfehler.
Vereinfachung des Connectors
Sie vereinfachen nun Ihren Connector, indem Sie die Parameter für Ihre Datenquellenfunktion (TripPin.Contents
) entfernen. Sie entfernen auch den shared
Qualifier für TripPin.Feed
und belassen ihn als rein interne Funktion.
Eine der Entwurfsphilosophien von Power Query besteht darin, den anfänglichen Datenquellendialog so einfach wie möglich zu halten. Wenn es möglich ist, sollten Sie dem Benutzer auf der Ebene des Navigators Auswahlmöglichkeiten anbieten, anstatt im Verbindungsdialog. Wenn ein vom Benutzer bereitgestellter Wert programmatisch bestimmt werden kann, sollten Sie ihn als oberste Ebene Ihrer Navigationstabelle hinzufügen, anstatt ihn als Funktionsparameter zu verwenden.
Wenn Sie beispielsweise eine Verbindung zu einer relationalen Datenbank herstellen, benötigen Sie möglicherweise Server-, Datenbank- und Tabellennamen.
Sobald Sie den Server kennen, mit dem Sie eine Verbindung herstellen wollen, und die Anmeldeinformationen vorliegen, können Sie die API der Datenbank verwenden, um eine Liste der Datenbanken und eine Liste der in jeder Datenbank enthaltenen Tabellen abzurufen.
Um den ersten Verbindungsdialog so einfach wie möglich zu halten, sollte in diesem Fall nur der Servername ein erforderlicher Parameter sein -Database
und Table
wären die Ebenen Ihrer Navigationstabelle.
Da der TripPin-Dienst einen festen URL-Endpunkt hat, müssen Sie den Benutzer nicht zur Eingabe von Werten auffordern. Sie entfernen den Parameter url aus Ihrer Funktion und definieren eine Variable BaseUrl in Ihrem Connector.
BaseUrl = "https://services.odata.org/v4/TripPinService/";
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;
Die Funktion TripPin.Feed
wird beibehalten, aber nicht mehr gemeinsam genutzt, nicht mehr mit einer Datenquellenart verknüpft und ihre Deklaration vereinfacht. Von nun an werden Sie es nur noch intern innerhalb dieses Abschnittsdokuments verwenden.
TripPin.Feed = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Wenn Sie den Aufruf TripPin.Contents()
in Ihrer Datei TripPin.query.pq
aktualisieren und in Visual Studio Code ausführen, wird eine neue Eingabeaufforderung für die Anmeldeinformationen angezeigt. Beachten Sie, dass es jetzt einen einzigen Datenquellenpfadwert gibt – TripPin.
Verbesserung der Navigationstabelle
Im ersten Tutorial von haben Sie die integrierten Funktionen von OData
verwendet, um eine Verbindung zum TripPin-Dienst herzustellen.
Auf diese Weise erhalten Sie eine schön aussehende Navigationstabelle, die auf dem TripPin-Dienstdokument basiert, ohne zusätzlichen Code auf Ihrer Seite.
Die Funktion OData.Feed hat die harte Arbeit automatisch für Sie erledigt.
Da Sie Web.Contents anstelle von OData.Feedverwenden, müssen Sie diese Navigationstabelle selbst neu erstellen.
Sie werden die folgenden Änderungen vornehmen:
- Definieren Sie eine Liste von Elementen, die in Ihrer Navigationstabelle angezeigt werden sollen
- Abschaffung der entitätsspezifischen Funktionen (
GetAirlineTables
undGetAirportsTable
)
Erzeugen einer Navigationstabelle aus einer Liste
In der Navigationstabelle führen Sie die Entitäten auf, die Sie offenlegen möchten, und erstellen die entsprechende URL für den Zugriff auf sie. Da alle Entitäten unter demselben Stammpfad liegen, können Sie diese URLs dynamisch erstellen.
Um das Beispiel zu vereinfachen, werden Sie nur die drei Entitätsgruppen (Fluggesellschaften, Flughäfen, Personen), die als Tabellen in M dargestellt werden, darstellen und das Singleton (Me), das als Datensatz dargestellt werden würde, weglassen. Das Hinzufügen der Funktionen wird auf eine spätere Lektion verschoben.
RootEntities = {
"Airlines",
"Airports",
"People"
};
Anschließend aktualisieren Sie Ihre TripPinNavTable
-Funktion, um die Tabelle spaltenweise aufzubauen.
Die Spalte [Daten] für jede Entität wird durch Aufruf von TripPin.Feed
mit der vollständigen URL der Entität abgerufen.
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;
Achten Sie beim dynamischen Aufbau von URL-Pfaden darauf, dass die Schrägstriche (/) eindeutig sind! Beachten Sie, dass Uri.Combine beim Kombinieren von Pfaden die folgenden Regeln verwendet:
- Wenn der Parameter
relativeUri
mit einem / beginnt, wird er den gesamten Pfad des ParametersbaseUri
ersetzen - Wenn der
relativeUri
-Parameter nicht mit einem / beginnt undbaseUri
mit einem / endet, wird der Pfad angehängt - Wenn der Parameter
relativeUri
nicht mit einem / undbaseUri
beginnt und nicht mit einem / endet, wird das letzte Segment des Pfades ersetzt
Das folgende Bild zeigt Beispiele dafür:
Entfernen Sie die entitätsspezifischen Funktionen
Um die Wartung Ihres Connectors zu vereinfachen, werden Sie die entitätsspezifischen Formatierungsfunktionen, die Sie in der vorherigen Lektion verwendet haben, entfernen: GetAirlineTables
und GetAirportsTable
.
Stattdessen aktualisieren Sie TripPin.Feed
, um die JSON-Antwort auf eine Weise zu verarbeiten, die für alle Ihre Entitäten funktioniert.
Konkret nehmen Sie das Feld value
der zurückgegebenen OData-JSON-Nutzdaten und konvertieren es von einer Liste von Datensätzen in eine Tabelle.
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;
Hinweis
Ein Nachteil der Verwendung eines generischen Ansatzes für die Verarbeitung Ihrer Entitäten ist, dass Sie die schönen Formatierungs- und Typinformationen für Ihre Entitäten verlieren. In einem späteren Abschnitt dieses Tutorials wird gezeigt, wie das Schema bei REST-API-Aufrufen durchgesetzt werden kann.
Zusammenfassung
In diesem Tutorial haben Sie Ihren Connector bereinigt und vereinfacht, indem Sie den Wert für den Datenquellenpfad korrigiert und ein flexibleres Format für Ihre Navigationstabelle gewählt haben. Nachdem Sie diese Schritte ausgeführt haben (oder den Beispielcode in diesem Verzeichnis verwenden), gibt die Funktion TripPin.Contents
eine Navigationstabelle in Power BI Desktop zurück.