Programmieren von Power BI-Semantikmodellen mit dem Tabellarischen Objektmodell (TOM)

Gilt für: SQL Server 2016 und höher Analysis Services Azure Analysis Services Fabric/Power BI Premium

Dieser Artikel wurde ursprünglich vom Power BI Customer Advisory Team (CAT) für Power BI Dev Camp erstellt, einer Sammlung von Sitzungen, Artikeln und Videos zur erweiterten Programmierung für Power BI.

Power BI Premium semantischen Modelle enthalten den XMLA-Endpunkt. Der Endpunkt ist für Power BI-Entwickler von Bedeutung, da er APIs für die Interaktion mit der Analysis Services-Engine bereitstellt, die im Power BI-Dienst ausgeführt wird, und zum direkten Programmieren für Power BI-Modelle. Eine wachsende Anzahl von Power BI-Experten hat festgestellt, dass sie Power BI-Modelle erstellen, anzeigen und verwalten können, indem sie bereits vorhandene Tools verwenden, die das XMLA-Protokoll wie SQL Server Management Studio, Tabular Editor und DAX Studio verwenden. Als .NET-Entwickler können Sie jetzt C#-Code in eine .NET-Anwendung schreiben, um Modelle direkt im Power BI-Dienst zu erstellen und zu ändern.

Das Tabular Object Model (TOM) ist eine .NET-Bibliothek, die eine abstrakte Ebene auf dem XMLA-Endpunkt bereitstellt. Entwickler können Code in Form eines intuitiven Programmiermodells schreiben, das Klassen wie Model, Table, Column und Measure enthält. Im Hintergrund übersetzt TOM die Lese- und Schreibvorgänge in Ihrem Code in HTTP-Anforderungen, die für den XMLA-Endpunkt ausgeführt werden.

Diagramm der Anwendung zum Modellieren über den XMLA-Endpunkt.

Der Schwerpunkt dieses Artikels liegt auf den ersten Schritten mit TOM und der Veranschaulichung, wie Sie den C#-Code schreiben, der zum Erstellen und Ändern von Modellen erforderlich ist, während sie im Power BI-Dienst ausgeführt werden. TOM kann jedoch auch in Szenarien verwendet werden, die den XMLA-Endpunkt nicht einbeziehen, z. B. bei der Programmierung für ein lokales Modell, das in Power BI Desktop ausgeführt wird. Weitere Informationen zur Verwendung von TOM mit Power BI Desktop finden Sie in der Blogreihe des Power BI CAT-Mitglieds Phil Seamark, und vergewissern Sie sich, dass sie watch video How to programm datasets using the Tabular Object Model (TOM) aus dem Power BI Dev Camp.

TOM stellt eine neue und leistungsstarke API für Power BI-Entwickler dar, die sich von den Power BI-REST-APIs unterscheidet. Es gibt zwar einige Überschneidungen zwischen diesen beiden APIs, aber jede dieser APIs enthält eine erhebliche Menge an Funktionen, die in der anderen nicht enthalten sind. Darüber hinaus gibt es Szenarien, in denen ein Entwickler beide APIs zusammen verwenden muss, um eine vollständige Lösung zu implementieren.

Erste Schritte mit dem tabellarischen Objektmodell

Das erste, was Sie abrufen müssen, bevor Sie mit TOM programmieren können, ist die URL für eine Arbeitsbereichsverbindung. Die Arbeitsbereichsverbindungs-URL verweist auf einen bestimmten Arbeitsbereich und wird verwendet, um eine Verbindungszeichenfolge zu erstellen, mit der Ihr Code eine Verbindung mit diesem Power BI-Arbeitsbereich und den darin ausgeführten Modellen herstellen kann. Navigieren Sie zunächst zur Seite Einstellungen eines Power BI-Arbeitsbereichs, der in einer dedizierten Kapazität ausgeführt wird.

Link zu Arbeitsbereichseinstellungen.

Hinweis

DER XMLA-Endpunkt wird nur für Modelle unterstützt, die in einer dedizierten Kapazität ausgeführt werden. Es ist nicht für Modelle verfügbar, die in einer freigegebenen Kapazität ausgeführt werden. Wenn Sie mit Modellen in einem Power BI Premium pro Benutzerkapazität arbeiten, können Sie eine Verbindung als Benutzer herstellen, aber keine Verbindung als Dienstprinzipal herstellen.

Nachdem Sie im Bereich Einstellungen zur Registerkarte Premium navigieren, kopieren Sie die Verbindungs-URL des Arbeitsbereichs in die Zwischenablage.

Arbeitsbereich Verbindungszeichenfolge in den Einstellungen des semantischen Modells.

Der nächste Schritt besteht darin, eine neue .NET-Anwendung zu erstellen, in die Sie den C#-Code schreiben, der mit TOM programmiert. Sie können eine Webanwendung oder eine Desktopanwendung mit .NET 5, .NET Core 3.1 oder älteren Versionen auf dem .NET Framework erstellen. In diesem Artikel erstellen wir eine einfache C#-Konsolenanwendung mit dem .NET 5 SDK.

Erstellen einer neuen Konsolenanwendung

Verwenden Sie zunächst die .NET CLI , um eine neue Konsolenanwendung zu erstellen.

dotnet new console --name`

Hinzufügen des NuGet-Pakets für tabellarische Objektmodelle

Fügen Sie nach dem Erstellen der Konsolenanwendung das NuGet-Paket Microsoft.AnalysisServices.AdomdClient.NetCore.retail.amd64 hinzu, das das Tabular Object Model (TOM) enthält. Sie können das Paket in einer .NET 5-Anwendung installieren, indem Sie die folgende .NET CLI verwenden:

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

Hinzufügen der Verbindungszeichenfolge

Wenn in Ihrem Projekt das NuGet-Paket mit installierter TOM-Bibliothek installiert ist, können Sie die herkömmliche Hallo Welt Anwendung mit TOM erstellen. Die Anwendung stellt mithilfe der Arbeitsbereichsverbindungs-URL eine Verbindung mit einem Power BI-Arbeitsbereich her, listet dann die Modelle im Arbeitsbereich auf und zeigt ihre Namen im Konsolenfenster an.

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 diesem Beispiel enthält die Verbindungszeichenfolge die Arbeitsbereichsverbindungs-URL, aber keine Informationen zum Benutzer. Wenn Sie die Konsolenanwendung mit diesem Code ausführen, beginnt die Anwendung mit der Ausführung, und Sie werden dann mit einem browserbasierten Fenster zur Anmeldung aufgefordert. Wenn Sie sich mit einem Benutzerkonto anmelden, das über Berechtigungen für den Zugriff auf den Arbeitsbereich verfügt, auf den die Arbeitsbereichsverbindungs-URL verweist, kann die TOM-Bibliothek ein Zugriffstoken abrufen, eine Verbindung mit dem Power BI-Dienst herstellen und die Modelle im Arbeitsbereich auflisten.

Weitere Informationen zum Herstellen einer Verbindung über den XMLA-Endpunkt finden Sie unter Sematic-Modellkonnektivität mit dem XMLA-Endpunkt – Herstellen einer Verbindung mit einem Premium-Arbeitsbereich.

Authentifizieren mit Benutzername und Kennwort

Für Entwicklungs- und Testszenarien, in denen die Sicherheit nicht so wichtig ist, können Sie Ihren Benutzernamen und Ihr Kennwort hart codieren, sodass Sie sich nicht jedes Mal interaktiv anmelden müssen, wenn Sie ein Programm zum Testen ihres Codes ausführen, wie im folgenden Code gezeigt:

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);

Authentifizieren anhand eines Dienstprinzipal

Es ist auch recht einfach, sich als Dienstprinzipal anstatt als Benutzer zu authentifizieren. Wenn Sie eine Microsoft Entra Anwendung mit einer Anwendungs-ID und einem Geheimen Anwendungsgeheimnis erstellt haben, können Sie Ihren Code authentifizieren, um als Dienstprinzipal für die Microsoft Entra-Anwendung auszuführen, indem Sie das folgende Codebeispiel verwenden:

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);

Um mit TOM zu programmieren und auf ein Modell als Dienstprinzipal zuzugreifen, müssen Sie eine Power BI-Einstellung auf Mandantenebene im Power BI-Admin-Portal konfigurieren. Die Schritte zum Konfigurieren von Power BI zur Unterstützung der Verbindung als Dienstprinzipal werden unter Einbetten von Power BI-Inhalten mit Dienstprinzipal und einem Anwendungsgeheimnis beschrieben.

Authentifizieren mit einem Microsoft Entra Zugriffstoken

TOM bietet auch Flexibilität beim Herstellen einer Verbindung mithilfe eines gültigen Microsoft Entra-Zugriffstokens. Wenn Sie über die Entwicklerkenntnisse zum Implementieren eines Authentifizierungsflusses mit Microsoft Entra-ID und zum Abrufen von Zugriffstoken verfügen, können Sie Ihre TOM-Verbindungszeichenfolge ohne Benutzernamen formatieren, aber stattdessen das Zugriffstoken als Kennwort angeben, wie im folgenden Codebeispiel gezeigt:

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);
}

Wenn Sie ein benutzerbasiertes Zugriffstoken erwerben, um eine Verbindung mit einem Power BI-Arbeitsbereich mit TOM herzustellen, stellen Sie sicher, dass Sie beim Abrufen des Zugriffstokens die folgenden delegierten Berechtigungen anfordern, um sicherzustellen, dass Sie über alle erforderlichen Erstellungsberechtigungen verfügen:

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",
};

Wenn Sie mit der Power BI-REST-API programmiert haben, erkennen Sie möglicherweise vertraute Berechtigungen wie Content.Create, Dataset.ReadWrite.All und Workspace.ReadWrite.All. Eine interessante Beobachtung ist, dass TOM denselben Satz delegierter Berechtigungen wie die Power BI-REST-API verwendet, die im Bereich der Microsoft Entra Ressourcen-ID von https://analysis.windows.net/powerbi/apidefiniert ist.

Die Tatsache, dass sowohl der XMLA-Endpunkt als auch die Power BI-REST-API denselben Satz delegierter Berechtigungen nutzen, hat seine Vorteile. Zugriffstoken können austauschbar zwischen TOM und der Power BI-REST-API verwendet werden. Nachdem Sie ein Zugriffstoken zum Aufrufen von TOM zum Erstellen eines neuen Modells erworben haben, können Sie dasselbe Zugriffstoken verwenden, um die Power BI-REST-API aufzurufen, um die Anmeldeinformationen für die Datenquelle festzulegen, wie weiter unten in diesem Artikel beschrieben.

Eine Sache, die Power BI-Programmierer in der Regel verwirrt, ist, dass Dienstprinzipale keine delegierten Berechtigungen verwenden. Stattdessen konfigurieren Sie beim Programmieren mit TOM den Zugriff für einen Dienstprinzipal, indem Sie ihn dem Zielarbeitsbereich als Mitglied in der Rolle Admin oder Member hinzufügen.

Grundlegendes zu Server-, Datenbank- und Modellobjekten

Das Objektmodell in TOM basiert auf einer Hierarchie mit dem Serverobjekt der obersten Ebene, das eine Auflistung von Database-Objekten enthält. Beim Programmieren mit TOM in Power BI stellt das Server-Objekt einen Power BI-Arbeitsbereich und das Database-Objekt ein Power BI-Modell dar.

Diagramm des tabellarischen Objektmodells mit allen Objekten

Jede Datenbank enthält ein Model-Objekt , das Lese-/Schreibzugriff auf das Datenmodell ermöglicht. Das Modell enthält Sammlungen für die Elemente eines Datenmodells, einschließlich DataSource, Tabelle, Beziehung, Perspektive, Kultur und Rolle.

Wie im Hallo Welt-Code gezeigt, sobald Sie den Server aufrufen. Stellen Sie eine Verbindung her, um zu ermitteln, welche Modelle in einem Power BI-Arbeitsbereich vorhanden sind, indem Sie die Datenbankauflistung des Serverobjekts auflisten, wie im folgenden Code gezeigt:

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

Sie können auch die GetByName-Methode verwenden, die vom Databases-Auflistungsobjekt verfügbar gemacht wird, um auf ein Modell anhand des Namens zuzugreifen, wie folgt:

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

Es ist wichtig, zwischen einem Database-Objektund seiner inneren Model-Eigenschaft zu unterscheiden. Sie können Datenbankobjekteigenschaften verwenden, um Modellattribute wie Name, ID, CompatibilityMode und CompatibilityLevel zu ermitteln. Es gibt auch eine EstimatedSize-Eigenschaft , die es ermöglicht, zu ermitteln, wie groß ein Modell gewachsen ist. Weitere Eigenschaften sind LastUpdate, LastProcessed und LastSchemaUpdate , mit denen Sie bestimmen können, wann das zugrunde liegende Modell zuletzt aktualisiert wurde und wann das Modellschema aktualisiert wurde.

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);
}

Während das Database-Objekt über eigene Eigenschaften verfügt, ist es das innere Model-Objekt eines Database-Objekts , das Ihnen die Möglichkeit bietet, das zugrunde liegende Datenmodell eines Modells zu lesen und in dieses zu schreiben. Hier sehen Sie ein einfaches Beispiel für die Programmierung des Datenbankmodellobjekts , um die Tables-Auflistung aufzulisten und zu ermitteln, welche Tabellen sich darin befinden.

Im TOM-Objektmodell verfügt jedes Table-Objekt über Auflistungsobjekte für seine Partitionen. Spalten, Measures und Hierarchien.

Diagramm des tabellarischen Objektmodells mit Tabelle, Partition, Spalte, Measure und Hierarchie

Nachdem Sie das Model-Objekt für eine Datenbank abgerufen haben, können Sie mithilfe der Find-Methode der Tables-Auflistung auf eine bestimmte Tabelle anhand des Namens im Modell zugreifen. Im Folgenden sehen Sie ein Beispiel zum Abrufen einer Tabelle mit dem Namen Sales und ermitteln deren Member, indem Sie die Columns-Auflistung und measures-Auflistung auflisten:

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);
}

Ändern von Modellen mit TOM

In den obigen Abschnitten haben Sie erfahren, wie Sie auf ein Database-Objekt und dessen Model-Objekt zugreifen, um das Datenmodell eines Modells zu überprüfen, das im Power BI-Dienst ausgeführt wird. Jetzt ist es an der Zeit, unser erstes Modellupdate mit TOM zu programmieren, indem Sie einer Tabelle ein Measure hinzufügen.

Die von Ihnen verwendete Kapazität muss für XMLA-Lese-/Schreibzugriff aktiviert sein. Standardmäßig ist die XmlA-Endpunktberechtigungseinstellung auf Lesen festgelegt, sodass sie explizit auf Schreibzugriff von einer Person mit Berechtigungen für Kapazität Admin festgelegt werden muss. Diese Einstellung kann auf der Seite Kapazitätseinstellungen im Admin-Portal angezeigt und aktualisiert werden.

XMLA-Einstellung Leseschreibvorgang im Admin-Portal.

Wenn der XMLA-Endpunkt für Lese-/Schreibzugriff konfiguriert wurde, können Sie der Sales-Tabelle ein neues Measure namens Sales Revenue hinzufügen, wie im folgenden Code gezeigt:

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();

Sehen wir uns diesen Code genauer an. Zunächst erstellen Sie ein neues Measure-Objekt mit dem neuen C#-Operator und geben Werte für Name, Expression und FormatString an. Anschließend fügen Sie das neue Measure-Objekt der Measures-Auflistung des Table-Zielobjekts hinzu, indem Sie die Add-Methode aufrufen. Rufen Sie schließlich die SaveChanges-Methode des Model-Objekts auf, um Ihre Änderungen zurück in das Modell im Power BI-Dienst zu schreiben.

Beachten Sie, dass Updates für ein Modell im Arbeitsspeicher im Batch gespeichert werden, bis Sie SaveChanges aufrufen. Stellen Sie sich ein Szenario vor, in dem Sie jede Spalte in einer Tabelle ausblenden möchten. Sie können zunächst eine foreach-Schleife schreiben, um alle Column-Objekte für eine Tabelle aufzulisten und die IsHidden-Eigenschaft für jedes Column-Objekt auf true festzulegen. Nach Abschluss der foreach-Schleife verfügen Sie über mehrere Spaltenupdates, die im Arbeitsspeicher im Batch gespeichert werden. Es ist jedoch der letzte Aufruf von SaveChanges , der alle Änderungen zurück an den Power BI-Dienst in einem Batch pusht, wie unten gezeigt:

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();

Angenommen, Sie möchten die FormatString-Eigenschaft für eine vorhandene Spalte aktualisieren. Die Columns-Auflistung macht eine Find-Methode verfügbar, um das Column-Zielobjekt abzurufen. Danach müssen Sie nur noch die FormatString-Eigenschaft festlegen und SaveChanges wie folgt aufrufen:

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();

Die Fähigkeit von TOM, dynamisch zu ermitteln, was sich in einem Modell befindet, bietet Möglichkeiten, Updates auf generische und umfassende Weise durchzuführen. Stellen Sie sich ein Szenario vor, in dem Sie ein Modell verwalten, das viele Tabellen und dutzende oder sogar Hunderte von Spalten basierend auf dem DateTime-Datentyp enthält. Sie können die FormatString-Eigenschaft für jede DateTime-Spalte im gesamten Modell gleichzeitig aktualisieren, indem Sie Folgendes verwenden:

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();

Aktualisieren von Modellen mit TOM

Nun führen wir einen typischen Modellwartungsvorgang aus. Wie Sie im folgenden Code sehen, ist es nicht sehr kompliziert, einen Modellaktualisierungsvorgang mithilfe von TOM zu starten:

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

Genau wie bei der manuellen und geplanten Modellaktualisierung werden Aktualisierungen über den XMLA-Endpunkt im Aktualisierungsverlauf angezeigt, jedoch mit der Bezeichnung Via XMLA Endpoint.

Dialogfeld

Hinweis

ToM bietet zwar die Möglichkeit, einen Aktualisierungsvorgang zu starten, kann jedoch keine Datenquellenanmeldeinformationen für ein Power BI-Modell festlegen. Um Modelle mit TOM zu aktualisieren, müssen Sie zuerst die Anmeldeinformationen für die Datenquelle in den Einstellungen des semantischen Modells oder mithilfe der Power BI-REST-APIs festlegen.

Erstellen und Klonen von Modellen

Stellen Sie sich vor, Sie müssen Power BI-Modelle mithilfe von in C# geschriebenem Code erstellen und klonen. Beginnen wir mit dem Schreiben einer wiederverwendbaren Funktion mit dem Namen CreateDatabase , die ein neues Database-Objekt erstellt, wie folgt:

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 diesem Beispiel verwenden wir zunächst die GetNewName-Methodedes Databases-Auflistungsobjekts , um sicherzustellen, dass der name des neuen Modells im Zielarbeitsbereich eindeutig ist. Danach können das Database-Objekt und das zugehörige Model-Objekt mit dem neuen C#-Operator erstellt werden, wie im folgenden Code gezeigt. Am Ende fügt diese Methode das neue Database-Objekt der Databases-Auflistung hinzu und ruft die Datenbank auf. Update-Methode .

Wenn Ihr Ziel darin besteht, ein vorhandenes Modell zu kopieren, anstatt ein neues zu erstellen, können Sie die folgende CopyDatabase-Methode verwenden, um ein Power BI-Modell zu klonen, indem Sie ein neues leeres Modell erstellen und dann CopyTo im Model-Objekt aufrufen, um das gesamte Datenmodell in das neu erstellte Modell zu kopieren.

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;
}

Erstellen eines realen Modells von Grund auf neu

Ok, stellen Sie sich jetzt vor, Sie haben gerade ein neues Modell von Grund auf neu erstellt, und jetzt müssen Sie TOM verwenden, um ein reales Datenmodell zu erstellen, indem Sie Tabellen, Spalten, Measures, Hierarchien und Tabellenbeziehungen hinzufügen. Sehen wir uns ein Codebeispiel an, das eine neue Tabelle erstellt, die definierte Spalten enthält, eine dreidimensionale Hierarchie mit drei Ebenen hinzufügt und sogar den M-Ausdruck für die zugrunde liegende Tabellenabfrage bereitstellt:

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;
}

Nachdem Sie eine Reihe von Hilfsmethoden zum Erstellen der Tabellen erstellt haben, können Sie diese wie folgt zusammensetzen, um ein Datenmodell zu erstellen:

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 macht eine Relationships-Auflistung für das Model-Objekt verfügbar, mit der Sie die Beziehungen zwischen den Tabellen in Ihrem Modell definieren können. Hier ist der Code, der zum Erstellen eines SingleColumnRelationship-Objekts erforderlich ist, das eine 1:n-Beziehung zwischen der Tabelle Products und der Tabelle Sales herstellt:

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

Nachdem Sie mit dem Hinzufügen der Tabellen und der Tabellenbeziehung fertig sind, speichern Sie Ihre Arbeit mit einem Aufruf des Modells. SaveChanges:

model.SaveChanges();

An diesem Punkt sollten Sie nach dem Aufrufen von SaveChanges in der Lage sein, das neue Modell im Power BI-Dienst zu sehen und es zum Erstellen neuer Berichte zu verwenden.

Modellbericht im Power BI-Dienst.

Wichtig

Denken Sie daran, dass Sie die Anmeldeinformationen der Datenquelle in den Einstellungen des semantischen Modells oder über die Power BI-REST-API angeben müssen, bevor Sie das Modell aktualisieren können.

Beispielprojekt

Das Beispielprojekt mit dem C#-Code, den Sie in diesem Artikel gesehen haben, finden Sie hier. Jetzt ist es an der Zeit, mit der Programmierung mit TOM zu beginnen und Möglichkeiten zu finden, diese leistungsstarke neue API bei der Entwicklung benutzerdefinierter Lösungen für Power BI zu nutzen.

Weitere Informationen

Semantische Modellkonnektivität mit dem XMLA-Endpunkt
Problembehandlung bei der XMLA-Endpunktkonnektivität