Share via


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

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

重要

表格式模型定義語言 (TMDL) 目前為預覽狀態。 預覽版時,功能和檔可能會變更。

表格式模型定義語言 (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 檔案:

  • cultures
  • 檢視方塊
  • 角色
  • 資料表

以及下列專案的 根檔案

  • [資料庫]
  • model
  • 關聯性
  • 運算式
  • datasources

以下是 TMDL 資料夾的範例:

具有模型 TMDL 標記法的資料夾

定義包括:

  • 資料庫定義的一個檔案。
  • 模型定義的一個檔案。
  • 模型中 所有 資料來源的一個檔案。
  • 模型中 所有 運算式的一個檔案。
  • 模型中 所有 關聯性的一個檔案。
  • 每個文化特性語言架構 都有 一個檔案。
  • 每個檢視方塊 都有 一個檔案。
  • 每個角色都有一個檔案。
  • 每個資料表都有一個檔案。
  • 資料表的所有內部中繼資料屬性 (資料行、階層、資料分割,...) 中繼資料都存在於父資料表 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 物件轉換成位元組資料流程,以便跨平臺儲存、傳輸和互通性。 Stream API 也可讓您控制要載入哪些 TMDL 檔,以及輸出哪些 TMDL 檔。

TMDL 資料流程序列化是由 MetadataSerializationCoNtext 類別處理。

深入瞭解 如何使用資料流程來回序列化 TMDL

TMDL 語言

物件宣告

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

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

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

measure 之類的 partition 物件具有預設屬性,可在物件宣告的相同行或多行運算式的相同行 () = 分隔符號之後指派:

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 Content 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
Annotation Text
StringExtendedProperty Text
DataSource 類型 DataSourceType 列舉
分割區 SourceType PartitionSourceType 列舉
ChangedProperty 屬性 屬性文字
ExternalModelRoleMember MemberType RoleMemberType 列舉
任何自訂 JSON 屬性 (例如 DataAccessOptions) JSON 文件 Json
LinguisticMetadata Content 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 Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • 物件與其子物件之間 (資料表 - > 量值) 。

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • 物件與其多行運算式之間 (資料表 - measure - >> expression) 。

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

Model 的資料庫和直接子物件不需要縮排,因為它們會隱含地假設在根 Model 或 Database 底下:

  • model
  • 資料表
  • 共用運算式
  • 角色
  • cultures
  • 檢視方塊
  • 關聯性
  • 資料來源
  • 查詢群組
  • 模型層級注釋
  • 模型層級擴充屬性

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

空白

TMDL 預設會將下列規則套用至屬性和運算式值內的空白字元,如果未包含在反引號 ``` () 或雙引號 (「) :

  • 在屬性值上,會修剪前置和尾端空白字元。
  • 在運算式上,會卸載運算式結尾的空白字元。
  • 空白字元行會修剪為空白行, (沒有空格/索引標籤) 。

大小寫

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

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

在還原序列化/讀取時,TMDL API 不區分大小寫。

考量與限制

現在您已瞭解 TMDL,請務必參閱 開始使用 TMDL ,瞭解如何取得及部署 Power BI 語意模型的 TMDL 模型標記法。