Tabular Model Definition Language (TMDL)

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

TmDL (Tabular Model Definition Language) è una sintassi di definizione del modello a oggetti per i modelli di dati tabulari a livello di compatibilità 1200 o superiore.

Gli elementi chiave di TMDL includono:

  • Compatibilità completa con l'intero modello a oggetti tabulare (TOM). Ogni oggetto TMDL espone le stesse proprietà di TOM.
  • Basato sul testo e ottimizzato per l'interazione umana e la leggibilità. TMDL usa una sintassi grammaticale simile a YAML. Ogni oggetto TMDL è rappresentato nel testo con delimitatori minimi e usa il rientro per contrassegnare le relazioni padre-figlio.
  • Esperienza di modifica migliore, in particolare sulle proprietà con espressioni di incorporamento di tipi di contenuto diversi, ad esempio DATA Analysis Expression (DAX) e M.
  • Migliore per la collaborazione grazie alla relativa rappresentazione di cartella in cui ogni oggetto modello ha una rappresentazione di file singola, rendendolo più descrittivo per il controllo del codice sorgente.

Un aspetto importante di TMDL è l'uso del rientro degli spazi vuoti per indicare una struttura di oggetti TOM. L'esempio seguente mostra quanto sia facile rappresentare un modello tabulare quando si usa 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]

Struttura di cartelle TMDL

A differenza di TMSL, TMDL usa una struttura di cartelle. La struttura di cartelle predefinita ha un solo livello di sottocartelle , tutte con file tmdl all'interno:

  • Culture
  • Prospettive
  • Ruoli
  • Tabelle

E file radice per:

  • banca dati
  • modello
  • Relazioni
  • Espressioni
  • origini dati

Ecco un esempio di cartella TMDL:

Cartella con una rappresentazione TMDL di un modello

Le definizioni includono:

  • Un file per la definizione del database.
  • Un file per la definizione del modello.
  • Un file per tutte le origini dati nel modello.
  • Un file per tutte le espressioni nel modello.
  • Un file per tutte le relazioni nel modello.
  • Un file per ogni schema linguistico delle impostazioni cultura di.
  • Un file per ogni prospettiva di.
  • Un file per ogni ruolo di.
  • Un file per ogni tabella di.
  • Tutte le proprietà dei metadati interni delle tabelle (Column, Hierarchies, Partitions,...) metadati si trovano nel file TMDL della tabella padre.

TMDL API

Analogamente a TMSL (Tabular Model Scripting Language), è disponibile una classe per gestire la serializzazione TMDL. Per TMDL, la classe è TmdlSerializer, nello spazio dei nomi Microsoft.AnalysisServices.Tabular.

La classe TmdlSerializer espone i metodi per serializzare e deserializzare i documenti TMDL:

Serializzazione cartelle

public static void SerializeDatabaseToFolder (Database database, string path)

  • Riceve un oggetto di database TOM e il percorso di output TMDL.
  • Serializza il database TOM in una rappresentazione di cartella TMDL.

Altre su come serializzare in una cartella.

public static Database DeserializeDatabaseFromFolder (string path)

  • Riceve un percorso completo di una cartella TMDL.
  • Restituisce la rappresentazione dell'oggetto di database TOM della cartella TMDL.

Altre su come deserializzare dalle cartelle.

Serializzazione di stringhe

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

  • Riceve un oggetto TOM e restituisce la relativa rappresentazione di testo TMDL.

Altre su come serializzare un oggetto in una stringa.

Serializzazione dei flussi

È possibile serializzare/deserializzare TMDL da/verso flussi, consentendo di convertire un oggetto TOM in flussi di byte per l'archiviazione, la trasmissione e l'interoperabilità tra piattaforme. L'API Stream consente anche di controllare quali documenti TMDL vengono caricati e quali documenti TMDL vengono restituiti.

La serializzazione del flusso TMDL viene gestita dalla classe MetadataSerializationContext.

Altre su come serializzare in/da TMDL usando flussi.

Linguaggio TMDL

Dichiarazione dell'oggetto

Ad eccezione dell'oggetto Server, TMDL espone l'intero albero di oggetti database nel spazio dei nomi Microsoft.AnalysisServices.Tabular.

Un oggetto TMDL viene dichiarato specificando il tipo di oggetto TOM seguito dal relativo nome. Nell'esempio di codice seguente ogni tipo di oggetto: model, table, column è seguito da un nome di oggetto.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Gli oggetti come partition o measure hanno proprietà predefinite che possono essere assegnate dopo il delimitatore uguale (=) nella stessa riga della dichiarazione dell'oggetto o nella riga seguente per un'espressione a più righe:

table Sales

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

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

Il nome dell'oggetto TMDL deve essere racchiuso tra virgolette singole (') se include uno dei caratteri seguenti:

  • Punto (.)
  • Uguale a (=)
  • Due punti (:)
  • Virgolette singole ()
  • Spazi vuoti ( )

Se un nome di oggetto contiene virgolette singole ('), usare due virgolette singole per eseguire l'escape.

Proprietà dell'oggetto

Le proprietà dell'oggetto vengono specificate dopo l'espressione a più righe della dichiarazione dell'oggetto o della proprietà predefinita dell'oggetto. I valori delle proprietà dell'oggetto vengono specificati dopo i due punti (:) delimitatore. Per esempio:

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"

Le regole seguenti si applicano ai valori delle proprietà:

  • Il valore deve trovarsi nella stessa riga che segue i due punti e non può contenere più righe.

  • Valori delle proprietà text

    • Le virgolette iniziali e finali sono facoltative e rimosse automaticamente durante la serializzazione.
    • Deve essere racchiuso tra virgolette doppie (") se il testo contiene spazi vuoti finali o iniziali.
    • Se racchiuso tra virgolette doppie, se il valore contiene virgolette doppie, usare due virgolette doppie per eseguirne l'escape (vedere displayFolder proprietà nell'esempio di codice precedente).
  • proprietà booleane possono essere impostate usando la sintassi standard della coppia chiave/valore, ad esempio con la proprietà 'isAvailableInMdx' nell'esempio precedente. Possono anche essere impostati usando una sintassi di scelta rapida in cui viene dichiarato solo il nome della proprietà e true è implicito. Vedere, ad esempio, la proprietà 'isHidden' nell'esempio precedente.

Riferimenti a oggetti denominati

Alcune proprietà dell'oggetto contengono riferimenti ad altri oggetti modello, ad esempio:

  • Riferimento alle colonne nei livelli della gerarchia.
  • Riferimento sortByColumn in ogni colonna della tabella.
  • Riferimento di tabella/colonna/misura in prospettive.

In TMDL, i riferimenti vengono eseguiti usando il nome dell'oggetto e seguono la stessa escape e virgolette singole (') racchiudendo i requisiti di dichiarazione dell'oggetto. Nell'esempio di codice seguente sono visualizzate le proprietà dell'oggetto che contengono un riferimento a un altro oggetto: column.sortByColumn, level.column, perspectiveMeasure.measure e perspectiveTable.table.


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

Se necessario per fare riferimento a un nome completo, TMDL usa notazione punto per fare riferimento a un oggetto, ad esempio: 'Table 1'.'Column 1'

Oggetti figlio

L'albero di oggetti TOM contiene oggetti figlio in molte posizioni e a livelli diversi. Per esempio:

  • Un oggetto modello contiene oggetti tabella, ruolo ed espressione.
  • Un oggetto tabella contiene oggetti colonna, misura e gerarchia.

TMDL non dichiara in modo esplicito le raccolte figlio. Tutti gli elementi figlio applicabili all'interno dell'ambito del rispettivo elemento padre costituiscono in modo implicito gli elementi della raccolta corrispondente. Ad esempio, tutti gli elementi di colonna all'interno dell'ambito di una determinata tabella diventano elementi della raccolta di colonne di tale tabella in TOM, come illustrato di seguito:

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

Gli oggetti figlio non devono essere contigui. Ad esempio, è possibile dichiarare colonne e misure in qualsiasi ordine e indeterminato.

Proprietà predefinite

Alcuni tipi di oggetto hanno una proprietà predefinita che la maggior parte del tempo viene considerata come espressioni. La proprietà predefinita è specifica del tipo di oggetto. Se applicabile, il valore o l'espressione della proprietà viene specificato dopo il delimitatore (=) uguale a , dopo la dichiarazione di sezione.

Sintassi supportata:

  • Il valore viene specificato nella stessa riga dell'intestazione di sezione.
  • Il valore viene specificato come espressione su più righe dopo l'intestazione di sezione.

Nell'esempio di codice seguente la misura Sales Amount e la Sales-Partition1 di partizione sono a riga singola e la misura Quantity è multilinea:

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

Espressioni

Esistono proprietà dell'oggetto che, mentre si tratta di una proprietà di testo in TOM, ottenere un'analisi speciale in TMDL. L'intero testo è letto verbatim perché può includere caratteri speciali come virgolette o parentesi quadre nelle espressioni M o DAX. Le espressioni possono essere multilinea o a riga singola. Se multilinea, devono trovarsi nella riga immediatamente successiva alla dichiarazione della proprietà o dell'oggetto.

Un valore di espressione in TMDL viene specificato seguendo un delimitatore uguale a (=) , come nell'esempio seguente:

table Table1

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

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

Le regole speciali seguenti si applicano alle espressioni:

  • Le espressioni a più righe devono essere rientrate in un livello più profondo per le proprietà dell'oggetto padre e l'intera espressione deve essere compresa in tale livello di rientro.
  • Tutti gli spazi vuoti di rientro esterni vengono rimossi oltre il livello rientrato dell'oggetto padre.
  • Gli spazi vuoti verticali (righe vuote senza spazi vuoti) sono consentiti e sono considerati parte dell'espressione.
  • Le righe vuote finali e gli spazi vuoti vengono rimossi.
  • Per applicare un rientro diverso o per mantenere le righe vuote finali o gli spazi vuoti, usare i tre backtick (```) che racchiudono.
  • Per impostazione predefinita, il serializzatore TMDL racchiuderà i backtick se il valore dell'espressione contiene qualsiasi elemento che potrebbe causare una modifica durante il round trip (ad esempio, spazi vuoti finali, righe vuote con spazi vuoti).

Le espressioni racchiuse con tre backtick (```) vengono lette verbatim, tra cui rientro, righe vuote e spazi vuoti. Il delimitatore deve essere applicato immediatamente dopo il segno di uguale (=) e la riga che segue l'espressione e non può avere nulla dopo di esso, come nell'esempio seguente:

table Table1

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

            ```

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

L'uso dei tre backticks (```) delimitatore è facoltativo e obbligatorio solo in situazioni univoche. Per la maggior parte delle situazioni, l'uso del rientro corretto e la dichiarazione dell'oggetto garantisce un'analisi corretta di qualsiasi espressione aggiunta alla proprietà .

Quando l'espressione è racchiusa tra i backtick, si applicano le regole seguenti:

  • Tutti gli elementi tra tre backtick (```) vengono considerati parte delle regole di rientro multiblocco e TMDL non vengono applicate. Il delimitatore finale determina il rientro all'interno dell'espressione.
  • Il rientro relativo all'interno dell'espressione viene mantenuto. Il delimitatore finale (```) determina il limite sinistro dell'espressione (vedere 'Measure1' nell'esempio precedente).

Le proprietà seguenti vengono considerate come espressioni:

Tipo di oggetto Proprietà Linguaggio delle espressioni
Misura Espressione DAX
MPartitionSource Espressione M
CalculatedPartitionSource Espressione DAX
QueryPartitionSource Quesito NativeQuery
CalculationItem Espressione DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
INDICATORE KPI StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Contenuto XML o Json
JsonExtendedProperty Valore Json
FormatStringDefintion Espressione DAX
DataCoverageDefinition Espressione DAX
CalculationGroupExpression Espressione DAX
NamedExpression Espressione DAX
DetailRowsDefinition Espressione DAX
TablePermission FilterExpression DAX
CalculatedColumn Espressione DAX

Proprietà predefinite per tipo di oggetto

La tabella seguente mostra la proprietà predefinita e il linguaggio delle espressioni in base al tipo di oggetto:

Tipo di oggetto Proprietà predefinita Linguaggio delle espressioni
Misura Espressione DAX
CalculatedColumn Espressione DAX
CalculationItem Espressione DAX
FormatStringDefinition Espressione DAX
DetailRowsDefinition Espressione DAX
CalculationExpression Espressione DAX
DataCoverageDefinition Espressione DAX
TablePermission FilterExpression DAX
ColumnPermission MetadataPermission MetadataPermission Enum
NamedExpression Espressione M
MPartitionSource Espressione M
CalculatedPartitionSource Espressione DAX
JsonExtendedProperty Valore Json
Annotazione Valore Testo
StringExtendedProperty Valore Testo
DataSource Digitare Enumerazione DataSourceType
Partizione SourceType di Enumerazione PartitionSourceType
ChangedProperty Proprietà testo proprietà
ExternalModelRoleMember MemberType enumerazione RoleMemberType
Qualsiasi proprietà JSON personalizzata (ad esempio DataAccessOptions) Documento JSON Json
LinguisticMetadata Contenuto Json

Descrizioni

TMDL fornisce il supporto di prima classe per le descrizioni. Ai fini della documentazione del modello, è consigliabile fornire descrizioni per ogni oggetto TOM. TMDL considera le descrizioni come una proprietà speciale con supporto esplicito per la sintassi. Seguendo gli esempi di molti altri linguaggi, le descrizioni vengono specificate sopra ogni dichiarazione di oggetto usando la sintassi triple-slash (///).

Non sono consentiti spazi vuoti tra la fine del blocco di descrizione e il token del tipo di oggetto.

Le descrizioni possono essere suddivise tra più righe. Il serializzatore TMDL suddivide le descrizioni degli oggetti in più righe per mantenere le righe del documento generate sotto la lunghezza massima. La lunghezza massima predefinita è 80 caratteri.

/// Table Description
table Sales

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

Dichiarazione parziale

TMDL non forza la dichiarazione di oggetto nello stesso documento. Tuttavia, è simile a classi parziali C# dove è possibile suddividere la definizione dell'oggetto tra più file. Ad esempio, è possibile dichiarare una definizione di tabella in un file [table].tmdl e quindi avere tutte le misure di tutte le tabelle definite in un singolo file [measures].tmdl, come illustrato di seguito:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Per evitare un errore di analisi, la stessa proprietà non può essere dichiarata due volte. Ad esempio, la dichiarazione di due misure con lo stesso nome per la stessa tabella in due documenti TMDL diversi genera un errore.

Riferimenti agli oggetti

È possibile fare riferimento a un altro oggetto TMDL usando la parola chiave ref ref seguita dal tipo di oggetto e dal nome.

Ad esempio, se si serializza un oggetto Column usando l'API di serializzazione di stringhe, il risultato sarà:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Ordinamento di raccolte deterministiche

La parola chiave ref viene usata anche per definire e mantenere l'ordinamento della raccolta nei round trip TOM TMDL. È particolarmente importante evitare diff del controllo del codice sorgente sugli oggetti TMDL che vengono serializzati in singoli file: tabelle, ruoli, impostazioni cultura e prospettive. La parola chiave ref ref viene usata nel file TMDL dell'oggetto padre per dichiarare l'ordinamento dell'elemento da 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'

Vengono applicate le regole seguenti:

  • Durante la deserializzazione TMDL:
    • Gli oggetti a cui viene fatto riferimento in TMDL ma con il file TMDL mancante vengono ignorati.
    • Gli oggetti non a cui si fa riferimento, ma con il file TMDL esistente, vengono aggiunti alla fine della raccolta.
  • Durante la serializzazione TMDL:
    • A tutti gli oggetti della raccolta in TOM viene fatto riferimento usando la parola chiave ref .
    • Le raccolte con un solo elemento non generano un riferimento.
    • Le righe vuote non vengono generate tra ref se lo stesso tipo di oggetto.

Delimitatori valore proprietà

Esistono solo due delimitatori/simboli per assegnare un valore di proprietà:

  • Uguale a (=)

  • Due punti (:)

    • Usato per ogni valore della proprietà non espressione. Inclusione di proprietà che contengono riferimenti al modello.

Indentazione

TMDL usa regole rigide di rientro degli spazi vuoti per denotare la struttura della gerarchia TOM. Un documento TMDL usa una singola scheda predefinita regola di rientro.

Ogni oggetto può avere tre livelli di rientro:

  • Livello 1 - Dichiarazione dell'oggetto
    • Livello 2 - Proprietà oggetto
      • Livello 3 - Espressioni a più righe delle proprietà oggetto

All'interno di un documento TMDL, il rientro viene applicato nei casi seguenti:

  • Tra un'intestazione di sezione dell'oggetto e le proprietà dell'oggetto (tabella - proprietà>).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Tra un oggetto e i relativi oggetti figlio (tabella - misure>).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Tra un oggetto e le relative espressioni su più righe (tabella - misura> - espressione>).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Le espressioni a più righe devono avere un rientro di un livello più profondo rispetto alle proprietà dell'oggetto e l'intera espressione deve trovarsi all'interno di tale livello di rientro (vedere espressioni).

Non è necessario impostare un rientro per database e oggetti figlio diretti di Model perché vengono considerati in modo implicito annidati nel modello radice o nel database:

  • modello
  • Tabelle
  • espressioni condivise
  • Ruoli
  • Culture
  • Prospettive
  • Relazioni
  • origini dati
  • gruppi di query
  • annotazioni a livello di modello
  • proprietà estese a livello di modello

Non seguendo queste regole di inserimento genera un errore di analisi.

Spazi vuoti

TMDL per impostazione predefinita applica le regole seguenti agli spazi vuoti all'interno dei valori di proprietà ed espressione, se non racchiusi all'interno di backticks (```) o virgolette doppie ("):

  • Nei valori delle proprietà, gli spazi vuoti iniziali e finali vengono tagliati.
  • Nelle espressioni, le righe di spazi vuoti alla fine delle espressioni vengono eliminate.
  • Le righe di spazi vuoti vengono tagliate in righe vuote (senza spazi/tabulazioni).

Involucro

Per impostazione predefinita, l'API TMDL per serializzare/scrivere usa camelCase, applicata a:

  • Tipi di oggetto
  • Parole chiavi
  • Valori di enumerazione

In caso di deserializzazione/lettura, l'API TMDL non fa distinzione tra maiuscole e minuscole.

Ora che si ha familiarità con TMDL, vedere Introduzione a TMDL per informazioni su come ottenere e distribuire una rappresentazione del modello TMDL di un modello semantico di Power BI.