Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem mehrteiligen Lernprogramm wird die Erstellung einer neuen Datenquellenerweiterung für Power Query behandelt. Das Lernprogramm soll sequenziell durchgeführt werden – jede Lektion baut auf dem connector auf, der in früheren Lektionen erstellt wurde, und fügt Ihrem Connector inkrementell neue Funktionen hinzu.
In dieser Lektion lernen Sie:
- Erstellen einer Basisfunktion, die eine REST-API mithilfe von Web.Contents aufruft
- Erfahren Sie, wie Sie Anforderungsheader festlegen und eine JSON-Antwort verarbeiten.
- Verwenden von Power BI Desktop zum Wrangieren der Antwort in ein benutzerfreundliches Format
Diese Lektion wandelt den OData-basierten Connector für den TripPin-Dienst (erstellt in der vorherigen Lektion) in einen Connector um, der etwas ähnelt, das Sie für jede RESTful-API erstellen würden. OData ist eine RESTful-API, aber eine mit einem festen Satz von Konventionen. Der Vorteil von OData besteht darin, dass es ein Schema, ein Datenabrufprotokoll und eine Standardabfragesprache bereitstellt. Wenn Sie die Verwendung von OData.Feed entfernen, müssen Sie diese Funktionen selbst in den Connector integrieren.
Zusammenfassung des OData-Connectors
Bevor Sie die OData-Funktionen aus Ihrem Connector entfernen, sehen wir uns kurz an, was sie derzeit (meist hinter den Kulissen) tut, um Daten aus dem Dienst abzurufen.
Öffnen Sie das TripPin-Erweiterungsprojekt aus Teil 1 in Visual Studio Code. Öffnen Sie die Abfragedatei und fügen Sie die folgende Abfrage ein:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
Öffnen Sie Fiddler, und bewerten Sie dann die aktuelle Power Query-Datei in Visual Studio Code.
In Fiddler gibt es drei Anforderungen an den Server:
-
/Me: Die tatsächliche URL, die Sie anfordern. -
/$metadata: Ein Aufruf, der von derOData.FeedFunktion automatisch ausgeführt wird, um Schema- und Typinformationen zur Antwort zu ermitteln. -
/Me/BestFriend: Eines der Felder, die (eifrig) gezogen wurden, als Sie den /Me Singleton aufgelistet haben. In diesem Fall führte der Anruf zu einem204 No ContentStatus.
Die M-Bewertung ist meist verzögert. In den meisten Fällen werden Datenwerte nur abgerufen oder gezogen, wenn sie benötigt werden. Es gibt Szenarien (z. B. den Fall /Me/BestFriend), in denen ein Wert eifrig gezogen wird. Dieses Verhalten tritt in der Regel auf, wenn Typinformationen für ein Element benötigt werden, und das Modul hat keine andere Möglichkeit, den Typ zu bestimmen, als den Wert abzurufen und zu prüfen. Das Machen von Dingen lazy (d. h. vermeiden sie eifrige Pulls) ist einer der wichtigsten Aspekte, um einen M-Verbinder performant zu machen.
Sehen Sie sich die Anforderungsheader an, die zusammen mit den Anfragen gesendet wurden, und das JSON-Format der Antwort auf die /Me-Anfrage.
{
"@odata.context": "https://services.odata.org/v4/TripPinService/$metadata#Me",
"UserName": "aprilcline",
"FirstName": "April",
"LastName": "Cline",
"MiddleName": null,
"Gender": "Female",
"Age": null,
"Emails": [ "April@example.com", "April@contoso.com" ],
"FavoriteFeature": "Feature1",
"Features": [ ],
"AddressInfo": [
{
"Address": "P.O. Box 555",
"City": {
"Name": "Lander",
"CountryRegion": "United States",
"Region": "WY"
}
}
],
"HomeAddress": null
}
Nach Beendigung der Auswertung der Abfrage sollte im PQTest-Ergebnisfenster der Wert "Record" für das Singleton "Me" angezeigt werden.
Wenn Sie die Felder im Ausgabefenster mit den Feldern vergleichen, die in der unformatierten JSON-Antwort zurückgegeben werden, stellen Sie fest, dass ein Konflikt auftritt. Das Abfrageergebnis enthält andere Felder (Friends, Trips, GetFriendsTrips), die in der JSON-Antwort nicht an einer beliebigen Stelle angezeigt werden. Die OData.Feed-Funktion fügt diese Felder automatisch basierend auf dem von $metadata zurückgegebenen Schema an den Datensatz an. Dieser Unterschied ist ein gutes Beispiel dafür, wie ein Connector die Antwort des Diensts erweitern und/oder neu formatieren kann, um eine bessere Benutzererfahrung zu ermöglichen.
Erstellen eines einfachen REST-Connectors
Fügen Sie ihrem Connector nun eine neue exportierte Funktion hinzu, die Web.Contents aufruft.
Um erfolgreiche Webanforderungen an den OData-Dienst vorzunehmen, müssen Sie jedoch einige Standard-OData-Header festlegen. Dazu definieren Sie einen allgemeinen Satz von Headern als neue Variable in Ihrem Connector:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
Sie ändern die Implementierung Ihrer TripPin.Feed Funktion, sodass anstelle der Verwendung von OData.FeedWeb.Contents verwendet wird, um eine Webanfrage zu erstellen und das Ergebnis als JSON-Dokument zu parsen.
TripPinImpl = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Denken Sie daran, Ihren Connector jetzt zu erstellen, da Sie Änderungen an der Connectordatei vorgenommen haben. Anschließend können Sie die Abfragedatei (TripPin.query.pq) auswerten. Das Ergebnis des /Me-Eintrags ähnelt nun dem unformatierten JSON, das sich in der Fiddler-Anforderung befand.
Wenn Sie Fiddler beim Ausführen der neuen Funktion beobachten, stellen Sie auch fest, dass die Auswertung jetzt eine einzelne Webanforderung statt drei vorgibt. Herzlichen Glückwunsch – Sie haben eine Leistungssteigerung von 300% erreicht! Sie haben nun alle Typ- und Schemainformationen verloren, aber es ist noch nicht erforderlich, sich auf diesen Teil zu konzentrieren.
Aktualisieren Sie Ihre Abfrage, um auf einige der TripPin-Entitäten/Tabellen zuzugreifen, z. B.:
https://services.odata.org/v4/TripPinService/Airlineshttps://services.odata.org/v4/TripPinService/Airportshttps://services.odata.org/v4/TripPinService/Me/Trips
Sie stellen fest, dass die Pfade, die früher schön formatierte Tabellen zurückgaben, nun ein Feld der obersten Ebene "value" mit einem eingebetteten [List] zurückgeben. Sie müssen einige Transformationen für das Ergebnis ausführen, um sie für Endbenutzernutzungsszenarien nutzbar zu machen.
Erstellen von Transformationen in Power Query
Obwohl es möglich ist, Ihre M-Transformationen von Hand zu erstellen, bevorzugen die meisten Personen die Verwendung von Power Query, um ihre Daten zu gestalten. Sie öffnen Ihre Erweiterung in Power BI Desktop und verwenden sie zum Entwerfen von Abfragen, um die Ausgabe in ein benutzerfreundlicheres Format umzuwandeln. Erstellen Sie Ihre Lösung neu, kopieren Sie die neue Erweiterungsdatei in Ihr Verzeichnis für Benutzerdefinierte Datenconnectors, und starten Sie Power BI Desktop neu.
Starten Sie eine neue leere Abfrage, und fügen Sie die folgende Zeile in die Bearbeitungsleiste ein:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
Achten Sie darauf, das Zeichen = einzuschließen.
Bearbeiten Sie die Ausgabe, bis sie wie der ursprüngliche OData-Feed aussieht – eine Tabelle mit zwei Spalten: AirlineCode und Name.
Die resultierende Abfrage sollte etwa wie folgt aussehen:
let
Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines"),
value = Source[value],
toTable = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
expand = Table.ExpandRecordColumn(toTable, "Column1", {"AirlineCode", "Name"}, {"AirlineCode", "Name"})
in
expand
Geben Sie der Abfrage einen Namen ("Airlines").
Erstellen Sie eine neue leere Abfrage. Verwenden Sie diesmal die Funktion TripPin.Feed, um auf die Entität „/Airports“ zuzugreifen. Wenden Sie Transformationen an, bis Sie etwas erhalten, das dem in der folgenden Tabelle ähnelt. Die übereinstimmende Abfrage folgt der Tabelle – geben Sie dieser Abfrage auch einen Namen ("Flughäfen") zu.
let
Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airports"),
value = Source[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"Name", "IcaoCode", "IataCode", "Location"}, {"Name", "IcaoCode", "IataCode", "Location"}),
#"Expanded Location" = Table.ExpandRecordColumn(#"Expanded Column1", "Location", {"Address", "Loc", "City"}, {"Address", "Loc", "City"}),
#"Expanded City" = Table.ExpandRecordColumn(#"Expanded Location", "City", {"Name", "CountryRegion", "Region"}, {"Name.1", "CountryRegion", "Region"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded City",{{"Name.1", "City"}}),
#"Expanded Loc" = Table.ExpandRecordColumn(#"Renamed Columns", "Loc", {"coordinates"}, {"coordinates"}),
#"Added Custom" = Table.AddColumn(#"Expanded Loc", "Latitude", each [coordinates]{1}),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Longitude", each [coordinates]{0}),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"coordinates"}),
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Name", type text}, {"IcaoCode", type text}, {"IataCode", type text}, {"Address", type text}, {"City", type text}, {"CountryRegion", type text}, {"Region", type text}, {"Latitude", type number}, {"Longitude", type number}})
in
#"Changed Type"
Sie können diesen Vorgang für weitere Pfade unter der Dienstleistung wiederholen. Sobald Sie fertig sind, fahren Sie mit dem nächsten Schritt zum Erstellen einer (simulierten) Navigationstabelle fort.
Simulieren einer Navigationstabelle
Jetzt erstellen Sie eine Tabelle (mit M-Code), die Ihre schön formatierten TripPin-Entitäten darstellt.
Starten Sie eine neue leere Abfrage, und rufen Sie den erweiterten Editor auf.
Fügen Sie die folgende Abfrage ein:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
Wenn Sie Ihre Einstellung "Datenschutzstufen" nicht auf "Einstellungen der Datenschutzebene immer ignorieren" (auch als "Schnelles Kombinieren" bezeichnet) festgelegt haben, wird eine Datenschutzaufforderung angezeigt.
Datenschutzaufforderungen werden angezeigt, wenn Sie Daten aus mehreren Quellen kombinieren und keine Datenschutzstufe für eine oder mehrere Quellen angegeben haben. Wählen Sie die Schaltfläche "Weiter " aus, und legen Sie die Datenschutzstufe der obersten Quelle auf "Öffentlich" fest.
Wählen Sie "Speichern" aus, und ihre Tabelle wird angezeigt. Obwohl diese Tabelle noch keine Navigationstabelle ist, stellt sie die grundlegenden Funktionen bereit, die Sie in einer nachfolgenden Lektion in eine tabelle umwandeln müssen.
Datenkombinationsprüfungen werden nicht durchgeführt, wenn innerhalb einer Erweiterung auf mehrere Datenquellen zugegriffen wird. Da alle Datenquellenaufrufe innerhalb der Erweiterung denselben Autorisierungskontext erben, nimmt man an, dass es "sicher" ist, sie zu kombinieren. Ihre Erweiterung wird immer als einzelne Datenquelle behandelt, wenn es um Datenkombinationsregeln geht. Benutzer erhalten weiterhin die regelmäßigen Datenschutzaufforderungen, wenn Sie Ihre Quelle mit anderen M-Quellen kombinieren.
Wenn Sie Fiddler ausführen und die Schaltfläche " Vorschau aktualisieren " im Power Query-Editor auswählen, notieren Sie sich die separaten Webanforderungen für jedes Element in Ihrer Navigationstabelle. Diese separaten Anforderungen deuten darauf hin, dass eine eifrige Auswertung auftritt, was beim Erstellen von Navigationstabellen mit vielen Elementen nicht ideal ist. Nachfolgende Lektionen zeigen, wie Sie eine korrekte Navigationstabelle erstellen, die Lazy Evaluation unterstützt.
Conclusion
In dieser Lektion haben Sie gezeigt, wie Sie einen einfachen Connector für einen REST-Dienst erstellen. In diesem Fall haben Sie eine vorhandene OData-Erweiterung in eine standardmäßige REST-Erweiterung (mit Web.Contents) umgewandelt, aber dieselben Konzepte gelten, wenn Sie eine neue Erweiterung von Grund auf neu erstellen.
In der nächsten Lektion nehmen Sie die in dieser Lektion erstellten Abfragen mit Power BI Desktop und verwandeln sie in eine echte Navigationstabelle innerhalb der Erweiterung.