TripPin parte 4 - Caminhos da fonte de dados

Este tutorial com 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 incrementalmente novos recursos ao seu conector.

Nesta lição, você irá:

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

Esta lição simplifica o conector criado na lição anterior, removendo seus 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, consulte a seção Caminhos da fonte de dados de Manipulando autenticação.

Caminhos da fonte de dados

Ao invocar 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 Tipo de Fonte de Dados e Caminho da 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 executar uma consulta que usa uma das funções, você receberá um prompt de credencial com menus suspensos que permite selecionar um caminho e um tipo de autenticação.

Credenciais com caminhos.

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 credenciais 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 credenciais será exibido para o novo caminho.

Você pode ver todas as credenciais armazenadas em cache na tabela Credenciais na janela M Query Output .

Guia Credenciais.

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

Simplificando o conector

Agora você simplificará seu conector removendo os parâmetros para sua função de fonte de dados (TripPin.Contents). Você também removerá o shared qualificador do TripPin.Feed, e o deixará como uma função apenas interna.

Uma das filosofias de design do Power Query é manter o diálogo inicial da fonte de dados o mais simples possível. Se possível, deve fornecer ao utilizador opções ao nível do Navigator, em vez de na caixa de diálogo de ligaçã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, você pode precisar de nomes de servidor, banco de dados e tabela. Depois de saber o servidor ao qual se conectar e as credenciais foram fornecidas, você pode 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 a caixa de diálogo de conexão inicial o mais simples possível, apenas o nome do servidor deve ser um parâmetro necessário —Database e Table seriam os níveis da sua tabela de navegação.

Como o serviço TripPin tem um ponto de extremidade de URL fixo, não é necessário solicitar nenhum valor ao usuário. Você removerá o parâmetro url da sua função e definirá uma variável BaseUrl no seu conector.

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

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

Você manterá a TripPin.Feed função, mas não a tornará mais compartilhada, não a associará mais a um tipo de fonte de dados e simplificará sua declaração. A partir deste ponto, 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 TripPin.Contents() chamada em seu TripPin.query.pq arquivo e executá-la no Visual Studio Code, verá um novo prompt de credenciais. Observe que agora há um único valor de Caminho da Fonte de Dados — TripPin.

Credenciais sem caminho.

Melhorar a tabela de navegação

No primeiro tutorial, você usou as funções integradas OData para se conectar ao serviço TripPin. Isso lhe deu uma mesa de navegação bonita, baseada no documento de serviço do TripPin, sem mais código do seu lado. A função OData.Feed automaticamente fez o trabalho duro para você. Uma vez que você está "aproximando-o" usando Web.Contents em vez de OData.Feed, você precisará recriar esta tabela de navegação por conta própria.

Navegador OData.

Você fará as seguintes alterações:

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

Gerar uma tabela de navegação a partir de uma lista

Você 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 sob o mesmo caminho raiz, você poderá criar essas URLs dinamicamente.

Para simplificar o exemplo, você exporá apenas os três conjuntos de entidades (Companhias Aéreas, Aeroportos, Pessoas), que seriam expostos como Tabelas em M, e ignorará o singleton (Me) que seria exposto como um Registro. Você pulará a adição das funções até uma lição posterior.

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

Em seguida, você atualiza sua TripPinNavTable função para criar a tabela uma coluna de cada vez. A coluna [Dados] de cada entidade é recuperada chamando TripPin.Feed com a URL completa para a 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, certifique-se de que está claro onde estão as barras (/)! Observe que Uri.Combine usa as seguintes regras ao combinar caminhos:

  • Quando o relativeUri parâmetro começa com um /, ele substituirá todo o baseUri caminho do 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 baseUri não terminar com um /, o último segmento do caminho será substituído

A imagem a seguir mostra exemplos disso:

Uri.Combine exemplo.

Remover as funções específicas da entidade

Para facilitar a manutenção do conector, você removerá as funções de formatação específicas da entidade usadas na lição anterior —GetAirlineTables e GetAirportsTable. Em vez disso, você atualizará TripPin.Feed para processar a resposta JSON de uma forma que funcione para todas as suas entidades. Especificamente, você pega o value campo da carga JSON OData retornada e o 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;

Nota

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

Conclusão

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

Navegador.

Próximos passos

TripPin Parte 5 - Paging