表格式模型定義語言 (TMDL)

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

表格式模型定義語言 (TMDL) 是相容性層級 1200 或更高層級表格式數據模型的物件模型定義語法。

TMDL 的主要元素包括:

  • 與整個 表格式物件模型 (TOM) 的完整相容性。 每個 TMDL 物件都會公開與 TOM 相同的屬性。
  • 以文字為基礎,並針對人類互動和可讀性進行優化。 TMDL 使用類似 YAML 的文法語法。 每個 TMDL 物件都會以最少分隔符在文字中表示,並使用縮排來標示父子關聯性。
  • 更好的編輯體驗,特別是在具有來自不同內容類型的內嵌表達式的屬性上,例如數據分析表達式 (DAX) 和 M。
  • 較適合共同作業,因為每個模型物件都有個別檔案表示法的資料夾表示法,因此更容易進行原始檔控制。

TMDL的重要層面是使用空格縮排來表示 TOM 對象結構。 下列範例顯示使用 TMDL 時,代表表格式模型是多麼容易:

database Sales
	compatibilityLevel: 1567

model Model    
    culture: en-US    

table Sales
    
    partition 'Sales-Partition' = m
        mode: import
        source = 
            let
                Source = Sql.Database(Server, Database)
                …
    
    measure 'Sales Amount' = SUMX('Sales', 'Sales'[Quantity] * 'Sales'[Net Price])
        formatString: $ #,##0
   
    column 'Product Key'
        dataType: int64
        isHidden
        sourceColumn: ProductKey
        summarizeBy: None
 
    column Quantity
        dataType: int64
        isHidden
        sourceColumn: Quantity
        summarizeBy: None

    column 'Net Price'
        dataType: int64
        isHidden
        sourceColumn: "Net Price"
        summarizeBy: none

table Product
    
    partition 'Product-Partition' = m
        mode: import
        source = 
            let
                Source = Sql.Database(Server, Database),
                …

    column 'Product Key'
        dataType: int64
        isKey
        sourceColumn: ProductKey
        summarizeBy: none

relationship cdb6e6a9-c9d1-42b9-b9e0-484a1bc7e123
    fromColumn: Sales.'Product Key'
    toColumn: Product.'Product Key'

role Role_Store1
    modelPermission: read

    tablePermission Store = 'Store'[Store Code] IN {1,10,20,30}

expression Server = "localhost" meta [IsParameterQuery=true, Type="Text", IsParameterQueryRequired=true]

expression Database = "Contoso" meta [IsParameterQuery=true, Type="Text", IsParameterQueryRequired=true]

TMDL 資料夾結構

與TMSL不同,TMDL 會使用資料夾結構。 預設資料夾結構只有一個層級 子資料夾,且所有資料夾內都有 .tmdl 檔案:

  • 文化
  • 觀點
  • 角色

根檔案

  • 資料庫
  • 關係
  • 表達式
  • 數據源

以下是 TMDL 資料夾的範例:

具有模型之 TMDL 表示法的 Folder

定義包括:

  • 資料庫定義的一個檔案。
  • 模型定義的一個檔案。
  • 一個用於 模型中所有 數據源的檔案。
  • 模型中所有 表示式 一個檔案。
  • 一個用於 模型中所有 關聯性的檔案。
  • 每個 文化特性語言架構 一個檔案。
  • 每個 檢視方塊 一個檔案。
  • 每個 角色 一個檔案。
  • 每個 數據表 一個檔案。
  • 數據表的所有內部元數據屬性(數據行、階層、數據分割,...)元數據都存在於父數據表 TMDL 檔案中。

TMDL API

類似於 表格式模型腳本語言 (TMSL),有一個類別可以處理 TMDL 串行化。 針對 TMDL,類別會在 Microsoft.AnalysisServices.Tabular 命名空間下,TmdlSerializer

TmdlSerializer 類別會公開方法來串行化和還原串行化 TMDL 檔:

資料夾序列化

public static void SerializeDatabaseToFolder (Database database, string path)

  • 接收 TOM 資料庫物件和 TMDL 輸出路徑。
  • 將 TOM 資料庫串行化為 TMDL 資料夾表示法。

深入瞭解如何串行化至資料夾的詳細資訊。

public static Database DeserializeDatabaseFromFolder (string path)

  • 接收 TMDL 資料夾的完整路徑。
  • 會傳回 TMDL 資料夾的 TOM 資料庫物件表示法。

深入瞭解如何從資料夾還原串行化

字串串列化

public static string SerializeObject (MetadataObject object, bool qualifyObject = true)

  • 接收 TOM 物件,並傳回其 TMDL 文字表示法。

深入瞭解如何將物件串行化為字串的詳細資訊

數據流串行化

您可以將 TMDL 串行化/還原串行化至數據流,讓您將 TOM 物件轉換成位元組資料流,以便跨平臺儲存、傳輸和互操作性。 串流 API 也可讓您控制要載入哪些 TMDL 檔,以及輸出哪些 TMDL 檔。

TMDL 數據流串行化是由 MetadataSerializationContext 類別處理。

深入瞭解如何使用數據流串行化至 TMDL 或從 TMDL 進行串行化

TMDL 語言

物件宣告

除了 Server 物件之外,TMDL 會在 Microsoft.AnalysisServices.Tabular 命名空間中公開整個 TOM Database 物件樹狀結構。

TMDL 對像是藉由指定 TOM 物件類型,後面接著其名稱來宣告。 在下列程式代碼範例中,每個物件類型:modeltablecolumn 後面接著物件名稱。

model Model    
    culture: en-US    

table Sales
    
    measure Sales = SUM(…)
        formatString: $ #,##0

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

partitionmeasure 等物件具有 預設屬性,可在物件宣告的相同行或多行表達式 表示式的同行=分隔符後面指派:

table Sales

    partition Sales-Part1 = m
        mode: import
        ...        
    
    measure Sales = SUM(…)
        formatString: $ #,##0

    measure 'Sales (ly)' = 
            var ly = ...
            return ly
        formatString: $ #,##0

如果 TMDL 物件名稱包含下列任何字元,則必須以單引弧括住 ('] :

  • 點 (.
  • 等號 (=
  • 冒號 (
  • 單引號 ('
  • 空白 ( )

如果物件名稱包含單引號 ('),請使用兩個單引號來逸出它。

物件屬性

物件屬性是在物件宣告或對象預設屬性多行表達式之後指定。 物件屬性值是在冒號 () 分隔符之後指定。 例如:

table Sales
    lineageTag: e9374b9a-faee-4f9e-b2e7-d9aafb9d6a91    

    column Quantity
        dataType: int64
        isHidden
        isAvailableInMdx: false
        sourceColumn: Quantity

    measure 'Sales Amount' = 
            var result = SUMX(...)
            return result
  formatString: $ #,##0
  displayFolder: " My ""Amazing"" Measures"

下列規則適用於屬性值:

  • 值必須位於冒號之後的同一行,而且不能有多行。

  • Text 屬性值

    • 前置和尾端雙引號是選擇性的,而且會在串行化期間自動移除。
    • 如果文字包含尾端或前置空格符,則必須以雙引弧括住 (]。
    • 以雙引弧括住時,如果值包含雙引號,請使用兩個雙引號來逸出它們(請參閱上述程式碼範例中的 displayFolder 屬性)。
  • 布爾值屬性 可以使用標準索引鍵/值組語法來設定,例如上一個範例中的 'isAvailableInMdx' 屬性。 您也可以使用快捷方式語法來設定它們,其中只會宣告屬性名稱,而且隱含 true。 例如,請參閱上一個範例中的 『isHidden』 屬性。

具名對象參考

某些物件屬性會保存其他模型對象的參考,例如:

  • 階層層級中的數據行參考。
  • 每個數據表數據行中的 sortByColumn 參考。
  • 檢視方塊中的數據表/數據行/量值參考。

在 TMDL 中,會使用物件名稱進行參考,並遵循物件宣告的相同逸出和單引號 (') 括住需求。 在下列程式代碼範例中,您會看到保存另一個對象的參考的物件屬性:column.sortByColumnlevel.columnperspectiveMeasure.measureperspectiveTable.table


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

如果需要參考完整名稱,TMDL 會使用 表示法來參考物件,例如:'Table 1'.'Column 1'

子物件

TOM 物件樹狀結構包含許多位置及不同層級的子物件。 例如:

  • 模型物件包含數據表、角色和表達式物件。
  • 數據表物件包含數據行、量值和階層物件。

TMDL 不會明確宣告子集合。 相反地,各自父代範圍內所有適用的子項目都會隱含地組成對應集合的元素。 例如,特定數據表範圍內的所有數據行元素都會成為 TOM 中該數據表之數據行集合的元素,如下所示:

table Sales

    measure 'Sales Amount' = SUMX('Sales', [Quantity] * [Net Price])

    measure 'Total Quantity' = SUM('Sales'[Quantity])

    measure 'Sales Amount YTD' = TOTALYTD([Sales Amount], 'Calendar'[Date])    

子物件不一定是連續的。 例如,您可以依任何順序和相互關聯來宣告數據行和量值。

默認屬性

某些物件類型具有預設屬性,大部分時間都會視為 表示式。 默認屬性是特定物件類型。 如果適用,屬性值或表達式是在區段宣告之後的等號 (=) 分隔符之後指定。

支援的語法:

  • 值是在與區段標頭相同的行上指定。
  • 值會在區段標頭之後指定為多行表達式。

在下列程式代碼範例中,量值 Sales Amount 和分割區 Sales-Partition1 為單行,而量值 Quantity 為多行:

table Sales

    measure 'Sales Amount' = SUM(...)
        formatString: $ #,##0

    measure Quantity = 
            var result = SUMX (...)
            return result
        formatString: #,##0

    partition Sales-Partition1 = m
  mode: import
  source =
   let
       ...
   in
       finalStep

表達式

有對象屬性,在 TOM 中是文字屬性時,在 TMDL 中取得特殊的剖析。 整個文字會逐字讀取,因為它可以在 M 或 DAX 運算式中包含特殊字元,例如引號或方括號。 表達式可以是多行或單行。 如果多行,它們必須緊接在屬性或物件宣告之後的行中。

TMDL 中的運算式值會指定為等於 (=) 分隔符,如下列範例所示:

table Table1

    partition 'partition 1' = m
        mode: import
        source =
            let
            ...
            in
                finalStep
    
    measure Measure1 = SUM(...)

    measure Measure2 =
            var result = SUMX ( 
                ...
            )
            return result
        formatString: $ #,##0

下列特殊規則適用於表示式:

  • 多行表達式必須縮排到父物件屬性更深的一個層級,而且整個表達式必須位於該縮排層級內。
  • 所有外部縮排空格符都會在父物件的縮排層級之外移除。
  • 允許垂直空格符(不含空格的空白行),並視為表達式的一部分。
  • 會移除尾端空白行和空格符。
  • 若要強制執行不同的縮排,或保留尾端空白行或空格符,請使用三個反引號 (```) 括住。
  • 根據預設,如果表達式值包含任何可能導致往返修改的專案,TMDL 串行化程式將會加上反引號(例如尾端空格符、空格符空白行)。

以三個反引號 (```) 括住的表達式會逐字讀取,包括縮排、空白行和空格符。 分隔符應該緊接在等號之後套用 (=), 表示式後面的行,而且後面不能有任何專案,如下列範例所示:

table Table1

    partition partition1 = m
        mode: import
        source = ```
            let
            ...
            in
                finalStep

            ```

    measure Measure1 = ```
                var myVar = Today()
                …
                return result
            ```

使用三個反引號 (```) 分隔符是選擇性的,只有在唯一的情況下才需要。 在大部分情況下,使用正確的縮排和物件宣告可確保正確剖析您新增至 屬性的任何表達式。

當運算式包含在反引號內時,會套用下列規則:

  • 三個反引號(```)之間的一切都會被視為多區塊表達式的一部分,而且不會套用 TMDL 縮排規則。 結尾分隔符會決定表達式內的縮排。
  • 表達式內的相對縮排會保留。 結尾分隔符 (```) 會決定表達式左邊界(請參閱上一個範例中的 'Measure1')。

下列屬性會被視為表示式:

物件類型 財產 表達式語言
表達 DAX
MPartitionSource 表達 M
CalculatedPartitionSource 表達 DAX
QueryPartitionSource 查詢 NativeQuery
CalculationItem 表達 DAX
BasicRefreshPolicy SourceExpression、PollingExpression M
KPI StatusExpression、TargetExpression、TrendExpression DAX
LinguisticMetadata 內容 XML 或 Json
JsonExtendedProperty 價值 Json
FormatStringDefintion 表達 DAX
DataCoverageDefinition 表達 DAX
CalculationGroupExpression 表達 DAX
NamedExpression 表達 DAX
DetailRowsDefinition 表達 DAX
TablePermission FilterExpression DAX
CalculatedColumn 表達 DAX

依物件類型的預設屬性

下表依物件類型顯示預設屬性和表示式語言:

物件類型 Default 屬性 表達式語言
表達 DAX
CalculatedColumn 表達 DAX
CalculationItem 表達 DAX
FormatStringDefinition 表達 DAX
DetailRowsDefinition 表達 DAX
CalculationExpression 表達 DAX
DataCoverageDefinition 表達 DAX
TablePermission FilterExpression DAX
ColumnPermission MetadataPermission MetadataPermission 列舉
NamedExpression 表達 M
MPartitionSource 表達 M
CalculatedPartitionSource 表達 DAX
JsonExtendedProperty 價值 Json
註解 價值 發簡訊
StringExtendedProperty 價值 發簡訊
DataSource 類型 DataSourceType 列舉
分區 SourceType PartitionSourceType 列舉
ChangedProperty 財產 屬性文字
ExternalModelRoleMember MemberType RoleMemberType 列舉
任何自訂 JSON 屬性 (例如 DataAccessOptions) JSON 檔 Json
LinguisticMetadata 內容 Json

描述

TMDL 提供描述的第一類支援。 針對模型檔用途,最佳做法是為每個 TOM 物件提供描述。 TMDL 會將描述視為具有明確語法支援的特殊屬性。 在許多其他語言的範例之後,會使用三斜線 (///) 語法,在每個物件宣告之上指定描述。

描述區塊結尾與物件類型令牌之間不允許空格符。

描述可以分割成多行。 TMDL 串行化程式會將物件描述分成多行,以將發出的檔行保持在最大長度之下。 預設的最大長度為80個字元。

/// Table Description
table Sales

    /// This is the Measure Description
    /// One more line
    measure 'Sales Amount'' = SUM(...)
        formatString: #,##0

部分宣告

TMDL 不會強制在同一份檔中宣告物件。 不過,這與 C# 部分類別類似, 可以在多個檔案之間分割物件定義。 例如,您可以在 [table].tmdl 檔案中宣告數據表定義,然後讓單一 [measures].tmdl 檔案中定義的所有數據表的所有量值,如下所示:

table Sales

    measure 'Sales Amount' = SUM(…)
        formatString: $ #,##0

table Product

    measure CountOfProduct = COUNTROWS(…)

為了避免剖析錯誤,無法宣告相同的屬性兩次。 例如,針對兩個不同 TMDL 檔中的相同數據表,宣告兩個具有相同名稱的量值會導致錯誤。

對象參考

您可以使用 ref 關鍵詞,後面接著物件類型和名稱來參考另一個 TMDL 物件。

例如,如果您使用字串串列化 API 串行化 Column 物件,結果會是:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

確定性集合順序

ref 關鍵詞也可用來定義及保留 TOM <> TMDL 往返的集合順序。 請務必避免原始檔控制差異在 TMDL 物件上串行化成個別檔案:數據表、角色、文化特性和檢視方塊。 ref 關鍵詞用於父物件 TMDL 檔案,以宣告從 TOM 排序的專案:


model Model

ref table Calendar
ref table Sales
ref table Product
ref table Customer
ref table About

ref culture en-US
ref culture pt-PT

ref role 'Stores Cluster 1'
ref role 'Stores Cluster 2'

套用下列規則:

  • 在 TMDL 還原串行化期間:
    • 會忽略 TMDL 中參考但缺少 TMDL 檔案的物件。
    • 未參考但具有現有 TMDL 檔案的物件會附加至集合結尾。
  • 在 TMDL 串行化期間:
    • TOM 中的所有集合物件都會使用 ref 關鍵詞來參考。
    • 只有一個專案的集合不會發出 ref。
    • 如果相同物件類型,則 ref 之間不會發出空白行。

屬性值分隔符

只有兩個分隔符/符號可以指派屬性值:

  • 等號 (=

  • 冒號 (

    • 每個非表示式 屬性值。 包含保存模型參考的屬性。

凹痕

TMDL 會使用嚴格的空格縮排規則來表示 TOM 階層的結構。 TMDL 檔會使用預設單一 索引標籤 縮排規則。

每個物件都可以有三個縮排層級:

  • 層級 1 - 物件宣告
    • 層級 2 - 物件屬性
      • 層級 3 - 物件屬性多行表達式

在 TMDL 檔中,縮排會在下列情況下套用:

  • 在物件區段標頭和對象的屬性之間 (table -> 屬性)。

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • 物件與其子對象之間(table -> 量值)。

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • 物件與其多行表達式之間(table -> 量值 -> 表示式)。

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • 多行表達式必須縮排一個比物件屬性更深的層級,而且整個運算式必須位於該縮排層級內(請參閱 運算式)。

模型的資料庫和直接子物件不需要縮排,因為它們會隱含地假設巢狀於根模型或資料庫底下:

  • 共用運算式
  • 角色
  • 文化
  • 觀點
  • 關係
  • 數據源
  • 查詢群組
  • 模型層級註釋
  • 模型層級擴充屬性

不遵循這些縮排規則會產生剖析錯誤。

空白

TMDL 預設會將下列規則套用至屬性和表示式值內的空格符,如果未包含在反引號(```)或雙引號內():

  • 在屬性值上,會修剪前置和尾端空格符。
  • 在表達式上,會卸除表達式結尾的空格符行。
  • 空格符行會修剪為空白行(無空格/索引卷標)。

套管

根據預設,串行化/寫入上的 TMDL API 會使用 camelCase套用至:

  • 物件類型
  • 關鍵字
  • 列舉值

在還原串行化/讀取上,TMDL API 不區分大小寫。

既然您已瞭解 TMDL,請務必看到 開始使用 TMDL,瞭解如何取得及部署 Power BI 語意模型的 TMDL 模型表示法。