Compartilhar via


TripPin parte 4 – Caminhos de fonte de dados

Este tutorial de várias partes aborda a criação de uma nova extensão de fonte de dados para o Power Query. O tutorial deve ser feito sequencialmente — cada lição se baseia no conector criado nas lições anteriores, adicionando progressivamente novos recursos ao conector.

Nesta lição, você:

  • Simplifique a lógica de conexão do seu conector
  • Melhorar a experiência da tabela de navegação

Esta lição simplifica o conector criado na lição anterior removendo os parâmetros de função necessários e melhorando a experiência do usuário movendo-se para uma tabela de navegação gerada dinamicamente.

Para obter uma explicação detalhada de como as credenciais são identificadas, vá para a seção Caminhos da Fonte de Dados do Tratamento da Autenticação.

Caminhos da fonte de dados

Quando você invoca uma função de fonte de dados, o mecanismo M identifica quais credenciais usar durante uma avaliação fazendo uma pesquisa com base nos valores de Tipo de Fonte de Dados e Caminho de Fonte de Dados.

Na lição anterior , você compartilhou duas funções de fonte de dados, ambas com um único parâmetro 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);

Na primeira vez que você executar uma consulta que utiliza uma das funções, você receberá uma solicitação de credenciais com menus suspensos. Esse prompt permite que você selecione um caminho e um tipo de autenticação.

Captura de tela da guia Erros da saída da consulta M mostrando a mensagem de credenciais.

Se você executar a mesma consulta novamente, com os mesmos parâmetros, o mecanismo M poderá localizar as credenciais armazenadas em cache e nenhum prompt de credencial será mostrado. Se você modificar o url argumento para sua função para que o caminho base não corresponda mais, um novo prompt de credencial será exibido para o novo caminho.

Todas as credenciais armazenadas em cache são exibidas na tabela Credenciais na janela Saída da Consulta M .

Captura de tela da saída da consulta M mostrando as credenciais armazenadas em cache na guia credenciais.

Dependendo do tipo de alteração, modificar os parâmetros da função provavelmente resultará em um erro de credencial.

Simplificando o conector

Agora simplifique o conector removendo os parâmetros para sua função de fonte de dados (TripPin.Contents). Você também precisa remover o shared qualificador para TripPin.Feed, e deixá-lo como uma função interna.

Uma das filosofias de design do Power Query é manter a caixa de diálogo da fonte de dados inicial o mais simples possível. Se possível, você deve fornecer ao usuário opções no nível do Navegador, em vez da caixa de diálogo de conexão. Se um valor fornecido pelo usuário puder ser determinado programaticamente, considere adicioná-lo como o nível superior da tabela de navegação em vez de um parâmetro de função.

Por exemplo, ao se conectar a um banco de dados relacional, talvez seja necessário nomes de servidor, banco de dados e tabela. Depois de conhecer o servidor ao qual se conectar e as credenciais forem fornecidas, você poderá usar a API do banco de dados para buscar uma lista de bancos de dados e uma lista de tabelas contidas em cada banco de dados. Nesse caso, para manter o diálogo de conexão inicial o mais simples possível, somente o nome do servidor deve ser um parâmetro necessário — Database e Table são níveis da tabela de navegação.

Como o serviço TripPin tem um endpoint de URL fixo, você não precisa solicitar nenhum valor ao usuário. Você precisa remover o parâmetro de URL da função e definir uma variável BaseUrl no conector.

BaseUrl = "https://services.odata.org/v4/TripPinService/";

[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;

Você mantém a TripPin.Feed função, mas não a torna mais compartilhada, não a associa mais a um Tipo de Fonte de Dados e simplifica sua declaração. Deste ponto em diante, você só o usará internamente neste documento de seção.

TripPin.Feed = (url as text) =>
    let
        source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
        json = Json.Document(source)
    in
        json;

Se você atualizar a chamada TripPin.Contents() em seu arquivo TripPin.query.pq e executá-la no Visual Studio Code, haverá uma nova solicitação de credencial. Além disso, agora há um único valor de Caminho da Fonte de Dados — TripPin.

Captura de tela da aba Erros do resultado da consulta M mostrando a mensagem de credencial que se refere apenas ao caminho TripPin.

Aprimorando a tabela de navegação

No primeiro tutorial, você usou as funções internas OData para se conectar ao serviço TripPin. Essas funções proporcionaram uma tabela de navegação de aparência atraente, com base no documento do serviço TripPin, sem a necessidade de adicionar mais código por sua parte. A função OData.Feed fez automaticamente o trabalho duro para você. Como você está "usando Web.Contents em vez de OData.Feed", você precisa recriar essa tabela de navegação por conta própria.

Captura de tela do Navegador do Power Query exibido ao usar as funções OData internas.

Você fará as seguintes alterações:

  1. Definir uma lista de itens a serem mostrados na tabela de navegação
  2. Acabar com as funções específicas da entidade (GetAirlineTables e GetAirportsTable)

Gerando uma tabela de navegação de uma lista

Você precisa listar as entidades que deseja expor na tabela de navegação e criar a URL apropriada para acessá-las. Como todas as entidades estão no mesmo caminho raiz, você pode criar essas URLs dinamicamente.

Para simplificar o exemplo, você expõe apenas os três conjuntos de entidades (Companhias Aéreas, Aeroportos, Pessoas), que seriam apresentados como Tabelas em M, e opta por não expor o singleton (Eu), que seria apresentado como um Registro. Você pode ignorar a adição das funções até uma lição posterior.

RootEntities = {
    "Airlines",
    "Airports",
    "People"
};

Em seguida, atualize sua TripPinNavTable função para criar uma coluna de cada vez na tabela. A coluna [Data] de cada entidade é recuperada ao chamar TripPin.Feed com a URL completa da entidade.

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;

Ao criar caminhos de URL dinamicamente, verifique se você está claro onde estão suas barras (/) para frente! O Uri.Combine usa as seguintes regras ao combinar caminhos:

  • Quando o relativeUri parâmetro começa com um /, ele substitui todo o caminho do baseUri parâmetro
  • Se o relativeUri parâmetro não começar com um /e baseUri terminar com um /, o caminho será acrescentado
  • Se o relativeUri parâmetro não começar com um /e baseUrinão terminar com um /, o último segmento do caminho será substituído

A imagem a seguir mostra exemplos dessas regras:

Captura de tela dos caminhos de URL mostrando as regras para barras de encaminhamento ao combinar caminhos.

Remover as funções específicas da entidade

Para facilitar a manutenção do conector, você precisa remover as funções de formatação específicas da entidade que você usou na lição anterior — GetAirlineTables e GetAirportsTable. Em vez disso, você atualiza TripPin.Feed para processar a resposta JSON de uma maneira que funcione para todas as suas entidades. Especificamente, você pega o value campo da carga JSON OData retornada e a converte de uma lista de registros em uma tabela.

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;

Observação

Uma desvantagem de usar uma abordagem genérica para processar suas entidades é que você perde a boa formatação e as informações de tipo para suas entidades. Uma seção posterior neste tutorial mostra como impor o esquema em chamadas à API REST.

Conclusion

Neste tutorial, você limpou e simplificou seu conector corrigindo o valor do Caminho da Fonte de Dados e tornando o formato da sua tabela de navegação mais flexível. Depois de concluir essas etapas (ou usar o código de exemplo neste diretório), a TripPin.Contents função retornará uma tabela de navegação no Power BI Desktop.

Captura de tela da tabela de navegação retornada pela função TripPin.Contents.

Próximas etapas

TripPin Capítulo 5 – Paginação