共用方式為


開始使用 TMDL

適用於: SQL Server 2016 和更新版本的 Analysis Services Azure Analysis Services Fabric/Power BI Premium

開始使用本文之前,請務必徹底瞭解 表格式模型定義語言 (TMDL) 概觀中所述的概念,

探索 TMDL 最簡單的方式是參考 Analysis Services 管理物件 (AMO) Nuget 套件,並使用 TMDL API 方法來串行化和還原串行化 TMDL。

取得 Nuget 套件

取得 TMDL 模型表示法

下列程式代碼範例示範如何在 Power BI Premium 工作區中取得語意模型的 TMDL 模型表示法:

var workspaceXmla = " <Workspace XMLA address>";
var datasetName = "<dataset name>";
var outputPath = System.Environment.CurrentDirectory;

using (var server = new Microsoft.AnalysisServices.Tabular.Server())
{
    server.Connect(workspaceXmla);

    var database = server.Databases.GetByName(datasetName);

    var destinationFolder = $"{outputPath}\\{database.Name}-tmdl";

    Microsoft.AnalysisServices.Tabular.TmdlSerializer.SerializeDatabaseToFolder(database.Model, destinationFolder);

}

輸出是具有模型 TMDL 表示法的資料夾,如下所示:

具有模型之 TMDL 表示法的 Folder

串行化至資料夾之後,請使用文字編輯器來編輯 TMDL 檔案。 例如,藉由使用 Visual Studio Code,我們可以新增量值,[銷售金額(計算機)]

/// Sales data for year over year analysis
table Sales        

    partition 'Sales-Part1' = m
        mode: Import        
        source =
            let
                …
            in
                #"Filtered Rows1"

    measure 'Sales Amount' = SUMX('Sales', [Quantity] * [Net Price])
        formatString: $ #,##0

    measure 'Sales Amount (Computers)' = CALCULATE([Sales Amount], 'Product'[Category] = "Computers")
        formatString: $ #,##0

為了獲得更好的體驗,您可以安裝 Visual Studio Code TMDL 語言延伸模組

部署 TMDL 模型表示法

下列程式代碼範例示範如何將模型的 TMDL 模型表示法部署到 Power BI Premium 工作區:

var xmlaServer = "<Workspace XMLA address>";

var tmdlFolderPath = $"{System.Environment.CurrentDirectory}\\Contoso-tmdl";

var model = Microsoft.AnalysisServices.Tabular.TmdlSerializer.DeserializeModelFromFolder(tmdlFolderPath);            

using (var server = new Microsoft.AnalysisServices.Tabular.Server())
{
    server.Connect(xmlaServer);

    using (var remoteDatabase = server.Databases[model.Database.ID])
    {
        model.CopyTo(remoteDatabase.Model);

        remoteDatabase.Model.SaveChanges();
    }               
}

執行時,新的量值會部署到模型。

數據集中 Sales Amount (Computers) 量值

處理 TMDL 串行化錯誤

在 TMDL 串行化方法中偵測到錯誤時,除了擲回一些常見的 .NET 例外狀況,例如 ArgumentExceptionInvalidOperationException之外,也會傳回 TMDL 特定的例外狀況。

  • 如果 TMDL 文字不是有效的語法,則會擲回 TmdlFormatException。 例如,無效的關鍵詞或縮排。

  • 如果 TMDL 文字有效,但違反 TOM 元數據邏輯,則會擲回 TmdlSerializationException。 例如,值的類型不符合預期的類型。

除了例外狀況詳細數據之外,還包含下列專案:

  • document path:TMDL 檔案的路徑,並出現錯誤。
  • line number:有錯誤的行號。
  • line text:有錯誤的行文字。

處理 TmdlFormatException的程式代碼範例:

try
{
    var tmdlPath = "<TMDL Folder Path>";

    var model = Microsoft.AnalysisServices.Tabular.TmdlSerializer.DeserializeDatabaseFromFolder(tmdlPath);
}
catch (Microsoft.AnalysisServices.Tabular.Tmdl.TmdlFormatException ex)
{
    Console.WriteLine($"Error on Deserializing TMDL '{ex.Message}', document path: '{ex.Document}'  line number: '{ex.Line}', line text: '{ex.LineText}'");

    throw;
}    

物件文字串行化

下列程式代碼範例示範如何將數據行串行化為 TMDL:


var output = Microsoft.AnalysisServices.Tabular.TmdlSerializer.SerializeObject(model.Tables["Product"].Columns["ProductKey"], qualifyObject: true);

Console.WriteLine(output);

輸出:

ref table Product

 column ProductKey
  dataType: int64
  isKey
  formatString: 0
  isAvailableInMdx: false
  lineageTag: 4184d53e-cd2d-4cbe-b8cb-04c72a750bc4
  summarizeBy: none
  sourceColumn: ProductKey

  annotation SummarizationSetBy = Automatic

數據流串行化

下列程式代碼範例示範如何將語意模型串行化為單一文字變數:

var output = new StringBuilder();

foreach (Microsoft.AnalysisServices.Tabular.Serialization.MetadataDocument document in model.ToTmdl())
{
    using (TextWriter writer = new StringWriter(output))
    {
        document.WriteTo(writer);
    }
}

Console.WriteLine(output.ToString());

下列程式代碼範例示範如何從 TMDL 還原串行化,但不包括角色:

var context = Microsoft.AnalysisServices.Tabular.Serialization.MetadataSerializationContext.Create(MetadataSerializationStyle.Tmdl);

var files = Directory.GetFiles("[TMDL Directory Path]", "*.tmdl", SearchOption.AllDirectories);

foreach (var file in files)
{
    if (file.Contains("/roles/"))
        continue;

    using (TextReader reader = File.OpenText(file))
    {                    
        context.ReadFromDocument(file, reader);
    }
}

var model = context.ToModel();