Programmazione di modelli semantici di Power BI con il modello a oggetti tabulare (TOM)

Si applica a: SQL Server 2016 e versioni successive di Analysis Services Azure Analysis Services Fabric/Power BI Premium

Questo articolo è stato originariamente creato dal team di consulenza clienti di Power BI per Power BI Dev Camp, una raccolta di sessioni, articoli e video sulla programmazione avanzata per Power BI.

Power BI Premium modelli semantici includono l'endpoint XMLA. L'endpoint è significativo per gli sviluppatori di Power BI perché fornisce API per interagire con il motore di Analysis Services in esecuzione nel servizio Power BI e programmare direttamente nei modelli di Power BI. Un numero crescente di professionisti di Power BI ha scoperto di poter creare, visualizzare e gestire modelli di Power BI usando strumenti preesistenti che usano il protocollo XMLA, ad esempio SQL Server Management Studio, Editor tabulare e DAX Studio. Gli sviluppatori .NET possono ora scrivere codice C# in un'applicazione .NET per creare e modificare modelli direttamente nel servizio Power BI.

Il modello a oggetti tabulare (TOM) è una libreria .NET che fornisce un livello astratto sopra l'endpoint XMLA. Consente agli sviluppatori di scrivere codice in termini di un modello di programmazione intuitivo che include classi come Model, Table, Column e Measure. In background, TOM converte le operazioni di lettura e scrittura nel codice in richieste HTTP eseguite sull'endpoint XMLA.

Diagramma dell'applicazione da modellare tramite l'endpoint XMLA.

L'obiettivo di questo articolo è iniziare a usare TOM e dimostrare come scrivere il codice C# necessario per creare e modificare modelli durante l'esecuzione nel servizio Power BI. Tuttavia, TOM può essere usato anche in scenari che non coinvolgono l'endpoint XMLA, ad esempio durante la programmazione su un modello locale in esecuzione in Power BI Desktop. Per altre informazioni sull'uso di TOM con Power BI Desktop, vedere la serie di blog di Phil Seamark del membro Power BI CAT e assicurarsi di watch il video How to program using the Tabular Object Model (TOM) (Come programmare i set di dati usando il video Tabular Object Model (TOM) di Power BI Dev Camp.

TOM rappresenta un'API nuova e potente per gli sviluppatori di Power BI separata e distinta dalle API REST di Power BI. Anche se esistono alcune sovrapposizioni tra queste due API, ognuna di queste API include una quantità significativa di funzionalità non inclusa nell'altra. Inoltre, esistono scenari che richiedono a uno sviluppatore di usare entrambe le API insieme per implementare una soluzione completa.

Introduzione con il modello a oggetti tabulari

La prima cosa da ottenere prima di poter programmare con TOM è l'URL per una connessione all'area di lavoro. L'URL di connessione dell'area di lavoro fa riferimento a un'area di lavoro specifica e viene usata per creare una stringa di connessione che consente al codice di connettersi all'area di lavoro di Power BI e ai modelli in esecuzione all'interno. Per iniziare, passare alla pagina Impostazioni di un'area di lavoro di Power BI in esecuzione in una capacità dedicata.

Collegamento alle impostazioni dell'area di lavoro.

Nota

L'endpoint XMLA è supportato per i modelli in esecuzione solo in una capacità dedicata. Non è disponibile per i modelli in esecuzione in una capacità condivisa. Se si lavora con i modelli in un Power BI Premium per capacità utente, è possibile connettersi come utente ma non connettersi come entità servizio.

Quando si passa alla scheda Premium del riquadro Impostazioni , copiare l'URL di connessione dell'area di lavoro negli Appunti.

Stringa di connessione dell'area di lavoro nelle impostazioni del modello semantico.

Il passaggio successivo consiste nel creare una nuova applicazione .NET in cui si scrive il codice C# che programmi usando TOM. È possibile creare un'applicazione Web o un'applicazione desktop usando .NET 5, .NET Core 3.1 o versioni precedenti in .NET Framework. In questo articolo viene creata una semplice applicazione console C# con .NET 5 SDK.

Creare una nuova applicazione console

Per iniziare, usare l'interfaccia della riga di comando di .NET per creare una nuova applicazione console.

dotnet new console --name`

Aggiungere il pacchetto NuGet del modello a oggetti tabulari

Dopo aver creato l'applicazione console, aggiungere il pacchetto NuGet Microsoft.AnalysisServices.AdomdClient.NetCore.retail.amd64 che contiene il modello a oggetti tabulare (TOM). È possibile installare il pacchetto in un'applicazione .NET 5 usando l'interfaccia della riga di comando di .NET seguente:

dotnet add package Microsoft.AnalysisServices.NetCore.retail.amd64

Aggiungere la stringa di connessione

Quando il progetto include il pacchetto NuGet con la libreria TOM installato, è quindi possibile creare l'applicazione di Hello World tradizionale con TOM. L'applicazione si connette a un'area di lavoro di Power BI usando l'URL di connessione dell'area di lavoro e quindi enumera i modelli nell'area di lavoro e visualizza i relativi nomi nella finestra della console.

using System;
using Microsoft.AnalysisServices.Tabular;

class Program {
  static void Main() {

    // create the connect string
    string workspaceConnection = "powerbi://api.powerbi.com/v1.0/myorg/LearningTOM";
    string connectString = $"DataSource={workspaceConnection};";

    // connect to the Power BI workspace referenced in connect string
    Server server = new Server();
    server.Connect(connectString);

    // enumerate through models in workspace to display their names
    foreach (Database database in server.Databases) {
      Console.WriteLine(database.Name);
    }
  }
}

In questo esempio, il stringa di connessione contiene l'URL di connessione dell'area di lavoro, ma nessuna informazione sull'utente. Se si esegue l'applicazione console con questo codice, l'applicazione inizierà a essere eseguita e verrà visualizzata una finestra basata su browser per accedere. Se si accede con un account utente con autorizzazioni per accedere all'area di lavoro a cui fa riferimento l'URL di connessione dell'area di lavoro, la libreria TOM è in grado di acquisire un token di accesso, connettersi al servizio Power BI ed enumerare i modelli nell'area di lavoro.

Per altre informazioni sulla connessione tramite l'endpoint XMLA, vedere Connettività del modello sematico con l'endpoint XMLA - Connessione a un'area di lavoro Premium.

Autenticazione con nome utente e password

Per gli scenari di sviluppo e test in cui la sicurezza non è importante, è possibile impostare come hardcoded il nome utente e la password, eliminando la necessità di accedere in modo interattivo ogni volta che si esegue un programma per testare il codice, come illustrato nel codice seguente:

string workspaceConnection = "powerbi://api.powerbi.com/v1.0/myorg/YOUR_WORKSPACE";
string userId = "YOUR_USER_NAME";
string password = "YOUR_USER_PASSWORD";
string connectStringUser = $"DataSource={workspaceConnection};User ID={userId};Password={password};";
server.Connect(connectStringUser);

Autenticazione con un'entità servizio

È anche abbastanza facile eseguire l'autenticazione come entità servizio anziché come utente. Se è stata creata un'applicazione Microsoft Entra con un ID applicazione e un segreto dell'applicazione, è possibile autenticare il codice per l'esecuzione come entità servizio per l'applicazione Microsoft Entra usando l'esempio di codice seguente:

string workspaceConnection = "powerbi://api.powerbi.com/v1.0/myorg/YOUR_WORKSPACE";
string tenantId = "YOUR_TENANT_ID";
string appId = "YOUR_APP_ID";
string appSecret = "YOUR_APP_SECRET";
string connectStringApp = $"DataSource={workspaceConnection};User ID=app:{appId}@{tenantId};Password={appSecret};";
server.Connect(connectStringApp);

Per programmare con TOM e accedere a un modello come entità servizio, è necessario configurare un'impostazione di Power BI a livello di tenant nel portale di Power BI Amministrazione. I passaggi per la configurazione di Power BI per supportare la connessione come entità servizio sono descritti in Incorporare il contenuto di Power BI con un'entità servizio e un segreto dell'applicazione.

Autenticazione con un token di accesso Microsoft Entra

TOM offre anche flessibilità quando si stabilisce una connessione usando un token di accesso Microsoft Entra valido. Se si dispone delle competenze per gli sviluppatori per implementare un flusso di autenticazione con Microsoft Entra ID e acquisire i token di accesso, è possibile formattare il stringa di connessione TOM senza un nome utente, ma includere il token di accesso come password, come illustrato nell'esempio di codice seguente:

public static void ConnectToPowerBIAsUser() {
  string workspaceConnection = "powerbi://api.powerbi.com/v1.0/myorg/YOUR_WORKSPACE";
  string accessToken = TokenManager.GetAccessToken();  // you must implement GetAccessToken yourself
  string connectStringUser = $"DataSource={workspaceConnection};Password={accessToken};";
  server.Connect(connectStringUser);
}

Se si acquisisce un token di accesso basato sull'utente per connettersi a un'area di lavoro di Power BI con TOM, assicurarsi di richiedere le autorizzazioni delegate seguenti durante l'acquisizione del token di accesso per assicurarsi di disporre di tutte le autorizzazioni di creazione necessarie:

public static readonly string[] XmlaScopes = new string[] {
    "https://analysis.windows.net/powerbi/api/Content.Create",
    "https://analysis.windows.net/powerbi/api/Dataset.ReadWrite.All",
    "https://analysis.windows.net/powerbi/api/Workspace.ReadWrite.All",
};

Se si sta programmando con l'API REST di Power BI, è possibile riconoscere autorizzazioni note, ad esempio Content.Create, Dataset.ReadWrite.All e Workspace.ReadWrite.All. Un'osservazione interessante è che TOM usa lo stesso set di autorizzazioni delegate dell'API REST di Power BI definito nell'ambito del Microsoft Entra ID risorsa di https://analysis.windows.net/powerbi/api.

Il fatto che sia l'endpoint XMLA che l'API REST di Power BI condividono lo stesso set di autorizzazioni delegate offre i vantaggi. I token di accesso possono essere usati in modo intercambiabile tra TOM e l'API REST di Power BI. Dopo aver acquisito un token di accesso per chiamare TOM per creare un nuovo modello, è possibile usare lo stesso token di accesso per chiamare l'API REST di Power BI per impostare le credenziali dell'origine dati, come descritto più avanti in questo articolo.

Un aspetto che tende a confondere i programmatori di Power BI è che le entità servizio non usano autorizzazioni delegate. Al contrario, quando si programma con TOM si configura l'accesso per un'entità servizio aggiungendolo all'area di lavoro di destinazione come membro del ruolo di Amministrazione o Membro.

Informazioni sugli oggetti server, database e modello

Il modello a oggetti in TOM si basa su una gerarchia con l'oggetto Server di primo livello che contiene una raccolta di oggetti Database . Quando si programma con TOM in Power BI, l'oggetto Server rappresenta un'area di lavoro di Power BI e l'oggetto Database rappresenta un modello di Power BI.

Diagramma del modello a oggetti tabulare con tutti gli oggetti

Ogni database contiene un oggetto Model che fornisce l'accesso in lettura/scrittura al modello di dati. Il modello contiene raccolte per gli elementi di un modello di dati, tra cui DataSource, Table, Relationship, Perspective, Culture e Role.

Come illustrato nel codice Hello World, una volta chiamato il server. Connettersi, è possibile individuare facilmente i modelli esistenti all'interno di un'area di lavoro di Power BI enumerando tramite l'insieme Databases dell'oggetto Server, come illustrato nel codice seguente:

foreach (Database database in server.Databases) {
    Console.WriteLine(database.Name);
}

È anche possibile utilizzare il metodo GetByName esposto dall'oggetto insieme Databases per accedere a un modello in base al nome, come illustrato di seguito:

Database database = server.Databases.GetByName("Wingtip Sales");

È importante distinguere tra un oggetto Databasee la relativa proprietà Model interna. È possibile utilizzare le proprietà dell'oggetto Database per individuare gli attributi del modello, ad esempio Name, ID, CompatibilityMode e CompatibilityLevel. Esiste anche una proprietà EstimatedSize che consente di scoprire quanto è cresciuto un modello di grandi dimensioni. Altre proprietà includono LastUpdate, LastProcessed e LastSchemaUpdate che consentono di determinare quando il modello sottostante è stato aggiornato per l'ultimo aggiornamento e l'ultimo aggiornamento dello schema del modello.

public static void GetDatabaseInfo(string DatabaseName) {
  Database database = server.Databases.GetByName(DatabaseName);
  Console.WriteLine("Name: " + database.Name);
  Console.WriteLine("ID: " + database.ID);
  Console.WriteLine("CompatibilityMode: " + database.CompatibilityMode);
  Console.WriteLine("CompatibilityLevel: " + database.CompatibilityLevel);
  Console.WriteLine("EstimatedSize: " + database.EstimatedSize);
  Console.WriteLine("LastUpdated: " + database.LastUpdate);
  Console.WriteLine("LastProcessed: " + database.LastProcessed);
  Console.WriteLine("LastSchemaUpdate: " + database.LastSchemaUpdate);
}

Mentre l'oggetto Database ha le proprie proprietà, è l'oggetto Model interno di un oggetto Database che consente di leggere e scrivere nel modello di dati sottostante di un modello. Ecco un semplice esempio di programmazione dell'oggetto Model di database per enumerare l'insieme Tables e individuare le tabelle all'interno.

Nel modello a oggetti TOM ogni oggetto Table dispone di oggetti raccolta per le relative partizioni. colonne, misure e gerarchie.

Diagramma del modello a oggetti tabulare con tabella, partizione, colonna, misura e gerarchia

Dopo aver recuperato l'oggetto Model per un database, è possibile accedere a una tabella specifica in base al nome nel modello usando il metodo Find dell'insieme Tables . Di seguito è riportato un esempio di recupero di una tabella denominata Sales e l'individuazione dei relativi membri tramite l'enumerazione tramite l'insieme Columns e l'insieme Measures :

Model databaseModel = server.Databases.GetByName("Tom Demo").Model;

Table tableSales = databaseModel.Tables.Find("Sales");

foreach (Column column in tableSales.Columns) {
  Console.WriteLine("Coulumn: " + column.Name);
}

foreach (Measure measure in tableSales.Measures) {
  Console.WriteLine("Measure: " + measure.Name);
  Console.WriteLine(measure.Expression);
}

Modifica di modelli con TOM

Nelle sezioni precedenti è stato illustrato come accedere a un oggetto Database e al relativo oggetto Model per esaminare il modello di dati di un modello in esecuzione nel servizio Power BI. A questo punto è possibile programmare il primo aggiornamento del modello con TOM aggiungendo una misura a una tabella.

La capacità in uso deve essere abilitata per la lettura/scrittura XMLA. Per impostazione predefinita, l'impostazione delle autorizzazioni dell'endpoint XMLA è impostata su Lettura, pertanto deve essere impostata in modo esplicito su Lettura scrittura da parte di un utente con autorizzazioni di Amministrazione capacità. Questa impostazione può essere visualizzata e aggiornata nella pagina Impostazioni capacità del portale di Amministrazione.

Impostazione Lettura scrittura XMLA nel portale di Amministrazione.

Quando l'endpoint XMLA è stato configurato per la lettura/scrittura, è quindi possibile aggiungere una nuova misura denominata Sales Revenue alla tabella Sales , come illustrato nel codice seguente:

Model dataset = server.Databases.GetByName("Tom Demo Starter").Model;
Table tableSales = dataset.Tables.Find("Sales");
Measure salesRevenue = new Measure();
salesRevenue.Name = "Sales Revenue";
salesRevenue.Expression = "SUM(Sales[SalesAmount])";
salesRevenue.FormatString = "$#,##0.00";
tableSales.Measures.Add(salesRevenue);
dataset.SaveChanges();

Esaminiamo più da vicino questo codice. Creare prima di tutto un nuovo oggetto Measure usando il nuovo operatore C# e specificare i valori per Name, Expression e FormatString. Aggiungere quindi il nuovo oggetto Measure all'insieme Measures dell'oggetto Table di destinazione chiamando il metodo Add . Infine, chiamare il metodo SaveChanges dell'oggetto Model per scrivere nuovamente le modifiche nel modello nel servizio Power BI.

Tenere presente che gli aggiornamenti a un modello vengono inseriti in batch in memoria fino a quando non si chiama SaveChanges. Si supponga uno scenario in cui si vuole nascondere ogni colonna in una tabella. È possibile iniziare scrivendo un ciclo foreach per enumerare tutti gli oggetti Column per una tabella e impostando la proprietà IsHidden per ogni oggetto Column su true. Al termine del ciclo foreach , sono disponibili diversi aggiornamenti delle colonne in batch in memoria. Ma è la chiamata finale a SaveChanges che esegue il push di tutte le modifiche al servizio Power BI in un batch, come illustrato di seguito:

Model dataset = server.Databases.GetByName("Tom Demo").Model;
Table tableSales = dataset.Tables.Find("Sales");

foreach (Column column in tableSales.Columns) {
  column.IsHidden = true;
}

dataset.SaveChanges();

Si supponga di voler aggiornare la proprietà FormatString per una colonna esistente. L'insieme Columns espone un metodo Find per recuperare l'oggetto Column di destinazione. Dopo questo, è solo questione di impostare la proprietà FormatString e chiamare SaveChanges, come segue:

Model dataset = server.Databases.GetByName("Tom Demo").Model;
Table tableSales = dataset.Tables.Find("Products");
Column columnListPrice = tableSales.Columns.Find("List Price");
columnListPrice.FormatString = "$#,##0.00";
dataset.SaveChanges();

La capacità di TOM di individuare dinamicamente ciò che si trova all'interno di un modello offre opportunità di eseguire aggiornamenti in modo generico e spazzante. Si supponga uno scenario in cui si gestisce un modello con molte tabelle e decine o anche centinaia di colonne in base al tipo di dati DateTime . È possibile aggiornare la proprietà FormatString per ogni colonna DateTime nell'intero modello usando quanto segue:

Database database = server.Databases.GetByName("Tom Demo Starter");
Model datasetModel = database.Model;

foreach (Table table in datasetModel.Tables) {
  foreach (Column column in table.Columns) {
    if(column.DataType == DataType.DateTime) {
      column.FormatString = "yyyy-MM-dd";
    }
  }
}

datasetModel.SaveChanges();

Aggiornamento dei modelli con TOM

A questo punto si esegue un'operazione tipica di manutenzione del modello. Come si vede nel codice seguente, non è molto complicato avviare un'operazione di aggiornamento del modello usando TOM:

public static void RefreshDatabaseModel(string Name) {
  Database database = server.Databases.GetByName(Name);
  database.Model.RequestRefresh(RefreshType.DataOnly);
  database.Model.SaveChanges();
}

Analogamente all'aggiornamento manuale e pianificato del modello, gli aggiornamenti tramite l'endpoint XMLA vengono visualizzati nella cronologia degli aggiornamenti, ma con l'etichetta Tramite endpoint XMLA.

Finestra di dialogo Aggiorna cronologia

Nota

Anche se TOM offre la possibilità di avviare un'operazione di aggiornamento, non può impostare le credenziali dell'origine dati per un modello di Power BI. Per aggiornare i modelli con TOM, è prima necessario impostare le credenziali dell'origine dati nelle impostazioni del modello semantico o usando le API REST di Power BI.

Creazione e clonazione di modelli

Si supponga di avere un requisito per creare e clonare modelli di Power BI usando il codice scritto in C#. Iniziamo scrivendo una funzione riutilizzabile denominata CreateDatabase che crea un nuovo oggetto Database , come illustrato di seguito:

public static Database CreateDatabase(string DatabaseName) {

  string newDatabaseName = server.Databases.GetNewName(DatabaseName);
  var database = new Database() {
    Name = newDatabaseName,
    ID = newDatabaseName,
    CompatibilityLevel = 1520,
    StorageEngineUsed = Microsoft.AnalysisServices.StorageEngineUsed.TabularMetadata,
    Model = new Model() {
      Name = DatabaseName + "-Model",
      Description = "A Demo Tabular data model with 1520 compatibility level."
    }
  };

  server.Databases.Add(database);
  database.Update(Microsoft.AnalysisServices.UpdateOptions.ExpandFull);
  return database;

}

In questo esempio si inizierà usando il metodo GetNewNamedell'oggetto raccolta Database per assicurarsi che il nuovo nome del modello sia univoco nell'area di lavoro di destinazione. In seguito, l'oggetto Database e il relativo oggetto Model possono essere creati usando il nuovo operatore C# come illustrato nel codice seguente. Alla fine, questo metodo aggiunge il nuovo oggetto Database all'insieme Database e chiama il database. Metodo Update .

Se l'obiettivo è copiare un modello esistente anziché crearne uno nuovo, è possibile usare il metodo CopyDatabase seguente per clonare un modello di Power BI creando un nuovo modello vuoto e quindi chiamando CopyTo nell'oggetto Model per il modello di origine per copiare l'intero modello di dati nel modello appena creato.

public static Database CopyDatabase(string sourceDatabaseName, string DatabaseName) {
  Database sourceDatabase = server.Databases.GetByName(sourceDatabaseName);
  string newDatabaseName = server.Databases.GetNewName(DatabaseName);
  Database targetDatabase = CreateDatabase(newDatabaseName);
  sourceDatabase.Model.CopyTo(targetDatabase.Model);
  targetDatabase.Model.SaveChanges();
  targetDatabase.Model.RequestRefresh(RefreshType.Full);
  targetDatabase.Model.SaveChanges();
  return targetDatabase;
}

Creazione di un modello reale da zero

OK, si supponga di aver appena creato un nuovo modello da zero e ora è necessario usare TOM per comporre un modello di dati reale aggiungendo tabelle, colonne, misure, gerarchie e relazioni di tabella. Si esaminerà un esempio di codice che crea una nuova tabella che include colonne definite, aggiunge una gerarchia tridimensionale e fornisce anche l'espressione M per la query di tabella sottostante:

private static Table CreateProductsTable() {

  Table productsTable = new Table() {
    Name = "Products",
    Description = "Products table",
    Partitions = {
      new Partition() {
        Name = "All Products",
        Mode = ModeType.Import,
        Source = new MPartitionSource() {
          // M code for query maintained in separate source file
          Expression = Properties.Resources.ProductQuery_m
        }
      }
    },
    Columns = {
      new DataColumn() { Name = "ProductId", DataType = DataType.Int64, SourceColumn = "ProductId", IsHidden = true },
      new DataColumn() { Name = "Product", DataType = DataType.String, SourceColumn = "Product" },
      new DataColumn() { Name = "Description", DataType = DataType.String, SourceColumn = "Description" },
      new DataColumn() { Name = "Category", DataType = DataType.String, SourceColumn = "Category" },
      new DataColumn() { Name = "Subcategory", DataType = DataType.String, SourceColumn = "Subcategory" },
      new DataColumn() { Name = "Product Image", DataType = DataType.String, 
                        SourceColumn = "ProductImageUrl", DataCategory = "ImageUrl" }
     }
  };

  productsTable.Hierarchies.Add(
    new Hierarchy() {
      Name = "Product Category",
      Levels = {
        new Level() { Ordinal=0, Name="Category", Column=productsTable.Columns["Category"] },
        new Level() { Ordinal=1, Name="Subcategory", Column=productsTable.Columns["Subcategory"] },
        new Level() { Ordinal=2, Name="Product", Column=productsTable.Columns["Product"] }
      }
  });

  return productsTable;
}

Dopo aver creato un set di metodi helper per creare le tabelle, è quindi possibile crearli insieme per creare un modello di dati, come illustrato di seguito:

Model model = database.Model;
Table tableCustomers = CreateCustomersTable();
Table tableProducts = CreateProductsTable();
Table tableSales = CreateSalesTable();
Table tableCalendar = CreateCalendarTable();
model.Tables.Add(tableCustomers);
model.Tables.Add(tableProducts);
model.Tables.Add(tableSales);
model.Tables.Add(tableCalendar);

TOM espone un insieme Relationships nell'oggetto Model che consente di definire le relazioni tra le tabelle nel modello. Ecco il codice necessario per creare un oggetto SingleColumnRelationship che stabilisce una relazione uno-a-molti tra la tabella Products e la tabella Sales :

model.Relationships.Add(new SingleColumnRelationship {
  Name = "Products to Sales",
  ToColumn = tableProducts.Columns["ProductId"],
  ToCardinality = RelationshipEndCardinality.One,
  FromColumn = tableSales.Columns["ProductId"],
  FromCardinality = RelationshipEndCardinality.Many
});

Dopo aver aggiunto le tabelle e la relazione di tabella, salvare il lavoro con una chiamata al modello. SaveChanges:

model.SaveChanges();

A questo punto, dopo aver chiamato SaveChanges, è necessario poter visualizzare il nuovo modello creato nel servizio Power BI e iniziare a usarlo per creare nuovi report.

Report del modello nel servizio Power BI.

Importante

Tenere presente che è necessario specificare le credenziali dell'origine dati nelle impostazioni del modello semantico o tramite l'API REST di Power BI prima di poter aggiornare il modello.

Progetto di esempio

Il progetto di esempio con il codice C# visualizzato in questo articolo è disponibile qui. Ora è il momento di iniziare a programmare con TOM e di trovare modi per sfruttare questa nuova API potente nello sviluppo di soluzioni personalizzate per Power BI.

Vedi anche

Connettività del modello semantico con l'endpoint XMLA
Risolvere i problemi relativi alla connettività degli endpoint XMLA