DCube vous a offert pour ces Techdays 2015 une session spéciale sur l'analyse de données en temps réel (à voir ici). J'ai eu l'occasion de travailler sur ce projet qui vous a été présenté par Romain CASTERES et Anthony GUILLAUME. Lors de la réalisation du prototype, un des éléments que j'ai dû gérer est l'envoie des données traitées par Apache Storm dans PowerBI. Ce fût l'occasion de découvrir la preview de cet outil ainsi qu'une de ses nouvelles features : PowerBI Api. Dans cet article je propose un tour d'horizon des capacités de cette WebApi !

 

Introduction

PowerBI est un outil qui vous permet de réaliser très facilement des reportings de qualité. Il est ensuite possible de les regrouper dans des dashboards afin d'avoir une vue d'ensemble. Chaque groupe de reporting est lié à une source de données (Dataset). Parmi ces sources disponibles, on retrouve de grands classiques comme Excel, Sql Server Analysis Services, Dynamics ou encore Salesforce. En plus de ces sources on trouve aussi une solution "Data from anywhere" qui consiste en une WebApi manipulable via le protocole HTTP. Grâce à cette solution, vous pouvez directement créer des tables et stocker vos données dans le cloud.

Pour se créer un compte et obtenir plus d'informations sur cet outil, une seule adresse : http://www.powerbi.com 

 

Description de l'API

L'Api PowerBI est ni plus ni moins qu'un service REST. Toutefois, il faut prendre en considération qu'il n'est pas Restful, il est donc nécessaire de respecter la documentation fournit par Microsoft pour l'utiliser (documentation MSDN).

Avant de pouvoir utiliser le service, il faut être authentifié via OAuth 2.0 sur l'autorité https://login.windows.net/common.oauth2/authorize afin de disposer d'un token d'accès valide.

L'Api expose quatre opérations permettant de créer une source de données et de l'alimenter :

- Création d'un Dataset

- Lister les Datasets disponibles

- Ajouter un jeu de données dans une Table

- Supprimer toutes les données d'une Table

L'ensemble de ces actions a actuellement une Url de base dans la beta de PowerBI : https://api.powerbi.com/beta/myorg/datasets

Création d'un Dataset

Cette opération est certainement la plus importante car il faut définir un schéma de données et respecter une liste de types définit :

- Int64 : Entier 64bits signé

- Double : Nombre 64bits signé à virgule flottante.

- Boolean : Vrai ou faux

- Datetime : Une date, de préférence au format ISO

- String : Chaîne de caractères (128k max)

Pour décrire le schéma, il faut le définir au format JSON. Le Dataset est nommé et contient une liste de tables elles-même nommées. Chaque Table dispose d'une liste de colonnes ayant un nom et un type de données. Voici un exemple de JSON permettant de créer la structure d'une source de données contenant une table Product :

{
    "name": "MonDataset",
    "tables": [
        {
            "name": "Product",
            "columns": [
                {
                    "name": "Id",
                    "dataType": "Int64"
                },
                {
                    "name": "Price",
                    "dataType": "Double"
                },
                {
                    "name": "IsAvaible",
                    "dataType": "Boolean"
                },
                {
                    "name": "CreationDate",
                    "dataType": "DateTime"
                },
                {
                    "name": "Name",
                    "dataType": "String"
                }
            ]
        }
    ]
}

Pour créer cette structure, il faut envoyer une requête HTTP POST contenant  le JSON sur l'url de base de l'API. La réponse du service vous permettra d'obtenir l'identifiant du Dataset créé.

 

Lister les Datasets disponibles

La liste des Datasets peut-être récupérée via une requête HTTP GET sur l'url de base de l'API. Le JSON correspondant à la liste respecte cette structure :

{
    "datasets": [
        {
            "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "name": "dataset1"
        },
        {
            "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "name": "dataset2"
        }
    ]
}

 

Ajouter un jeu de données dans une table

L'ajout de données nécessite d'envoyer une requête HTTP POST contenant le JSON sur une url ayant en paramètre l'Id du Dataset et le nom de la table. Le format de cette Url est le suivant :

url/id/tables/tableName/rows

Pour reprendre l'exemple de notre table Produit dans l'Api Beta, cela donnerait :

https://api.powerbi.com/beta/myorg/datasets/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/tables/Product/rows/tables/Product/rows

Le JSON contenu dans le corps de la requête doit correspondre à une liste d'objet respectant la structure du schéma de la table. Voici un exemple d'insertion pour la table Product :

{
    "rows": [
        {
            "Id": 1,
            "Price": 500.00,
            "IsAvaible": true,
            "CreationDate": "02/11/2015",
            "Name": "Computer"
        }
    ]
}

 

Supprimer toutes les données d'une table

Pour supprimer les données il suffit d'envoyer une requête HTTP DELETE en respectant le format d'Url utilisé pour l'insertion des données (voir au-dessus).

 

PowerBI Api en .Net

Pour utiliser l'Api vous aurez besoin de plusieurs packages NuGet, notamment Microsoft.IdentityModel.Clients.ActiveDirectoryMicrosoft.Net.Http et Newtonsoft.Json. Le développement du projet pour les Techdays m'a incité à écrire une librairie. Vu que j'aime bien partager mon code je l'ai mis en Open source sur Github et j'ai publié un package NuGet. Cette librairie va réduire considérablement le code que vous aurez à produire !

Pour commencer, ajouter le package NuGet à votre projet :

PM> Install-Package PowerBI.Api.Client

A présent, il vous faut rajouter la section de configuration PowerBIConfiguration dans votre fichier .config :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="PowerBiConfiguration" type="PowerBI.Api.Client.Configuration.PowerBiConfiguration"/>
    </configSections>
    <PowerBIConfiguration>
        <OAuth 
            Authority="https://login.windows.net/common/oauth2/authorize"
	    Resource="https://analysis.windows.net/powerbi/api"
	    Client="MyClientId" 
	    User="MyUserName" 
	    Password="MyPassword"/>
        <Api Url="https://api.powerbi.com/beta/myorg/datasets" />
    </PowerBIConfiguration>
</configuration>

Dans la balise OAuth, il vous faudra saisir vos propres informations (Client, User, Password).

 Maintenant que la partie configuration est opérationnelle, il ne vous reste plus qu'à manipuler l'Api via la classe PowerBIClient. Il n'est pas possible de créer une instance de cette classe directement, il faut passer par la méthode :

public static void Do(Action<PowerBIClient> action)

L'action propose une instance authentifiée via OAuth2 et prête à l'emploi. Voici l'ensemble des méthodes permettant la manipulation de l'Api qui sont disponibles via l'instance de la classe :

/// <summary>
/// Renvoie la liste des Datasets.
/// </summary>
public IList<Dataset> GetDatasets()

/// <summary>
/// Renvoie l'Identifiant correspondant à un nom de Datasets.
/// </summary>
public string GetDatasetId(string datasetName)

/// <summary>
/// True si le Dataset correspondant à un nom existe
/// </summary>
public bool IsDatasetExist(string datasetName)

/// <summary>
/// True si le Dataset correspondant à un Identifiant existe
/// </summary>
public bool IsDatasetIdExist(string datasetId)

/// <summary>
/// Création d'un Dataset
/// <param name="datasetName">Nom du Dataset.</param>
/// <param name="types">Liste de types correspondant à des tables</param>
/// </summary>
public bool CreateDataset(string datasetName, params Type[] types)

/// <summary>
/// Insert une ligne dans la table correspond au type de l'objet passé en paramètre.
/// </summary>
public bool Insert(string datasetId, object obj)

/// <summary>
/// Insert plusieurs ligne dans la table correspond au type d'objet contenu dans la liste passé en paramètre.
/// </summary>
public bool InsertAll(string datasetId, IList<object> objs)

/// <summary>
/// Supprime toutes les lignes d'une table correspondant au type T.
/// </summary>
public bool Delete<T>(string datasetId)

Si l'on reprend l'exemple de la table Produit, voici le DTO correspondant à la structure de notre table :

using System;

namespace Exemple
{
	public class Product
	{
		public int Id { get; set; }
		public double Price { get; set; }
		public bool IsAvaible { get; set; }
		public DateTime CreationDate { get; set; }
		public string Name { get; set; }
	}
}

Et voici un exemple complet d'utilisation de toutes les méthodes de l'instance de PowerBiClient :

PowerBIClient.Do(api => {
    var isCreated = api.CreateDataset(DatasetName, typeof(Product));
    var datasetId = api.GetDatasetId(DatasetName);
    var isDatasetExist = api.IsDatasetExist(DatasetName);
    var isDatasetIdExist = api.IsDatasetIdExist(datasetId);
    var isObjectInsert = api.Insert(datasetId, new Product
    {
        CreationDate = DateTime.Now,
        Id = 1,
        IsAvaible = true,
        Name = "Computer",
        Price = 500.00
    });
    var isListInsert = api.InsertAll(datasetId, new List<object>
    {
        new Product
	{
		CreationDate = DateTime.Now,
		Id = 2,
		IsAvaible = true,
		Name = "Screen",
		Price = 120.00
	},
	new Product
	{
		CreationDate = DateTime.Now,
		Id = 3,
		IsAvaible = false,
		Name = "External HDD",
		Price = 75.00
	}
    });
    var isDelete = api.Delete<Product>(datasetId);
}

 

Conclusion

Vous pouvez retrouver l'ensemble des sources de ma librairie sur Github :

https://github.com/Vtek/PowerBI.Api.Client

Pour l'instant, il n'y a pas d'autre possibilité à exploiter sur PowerBI Api, mais je vais suivre attentivement l'évolution de cette dernière afin d'enrichir la bibliothèque. En attendant, si vous avez des suggestions ou que vous trouvez des bugs n'hésitez pas à ouvrir des issues sur le repository Githubhttps://github.com/Vtek/PowerBI.Api.Client/issues

 

A bientôt,

Sylvain


Arnaud Voisin

Data Engineer chez DCube

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *