Share via


Tabular Model Definition Language (TMDL)

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

Importante

Il linguaggio TMDL (Tabular Model Definition Language) è attualmente in anteprima. Quando è in anteprima, è probabile che le funzionalità e la documentazione cambino.

Il linguaggio 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 in testo con delimitatori minimi e usa il rientro per contrassegnare le relazioni padre-figlio.
  • Migliore esperienza di modifica, in particolare per le proprietà con espressioni di incorporamento di tipi di contenuto diversi, ad esempio DAX (Data Analysis Expression) e M.
  • Migliore per la collaborazione a causa della relativa rappresentazione di cartella in cui ogni oggetto modello ha una singola rappresentazione di file, rendendolo più semplice dal 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 con estensione tmdl all'interno:

  • cultures
  • prospettive
  • Ruoli
  • tabelle

E i file radice per:

  • database
  • model
  • relationships
  • espressioni
  • datasources

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.
  • Un file per ogni prospettiva.
  • Un file per ogni ruolo.
  • Un file per ogni tabella.
  • Tutte le proprietà dei metadati interni delle tabelle (Column, Hierarchies, Partitions,...) metadati si trovano nel file TMDL della tabella padre.

TMDL API

Analogamente al linguaggio 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 informazioni 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 informazioni 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 informazioni 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 informazioni 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 di database TOM nello 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 ('), utilizzare due virgolette singole per evitare l'escape.

Proprietà degli oggetti

Le proprietà dell'oggetto vengono specificate dopo la dichiarazione dell'oggetto o l'espressione a più righe della proprietà predefinita dell'oggetto. I valori delle proprietà dell'oggetto vengono specificati dopo il delimitatore due punti (:). Ad 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ò avere più righe.

  • Valori delle proprietà text

    • Le virgolette doppie 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 la proprietà nell'esempio di codice precedente).
  • Le proprietà booleane possono essere impostate usando la sintassi della coppia chiave/valore standard, ad esempio con la 'isAvailableInMdx' proprietà nell'esempio precedente. Possono anche essere impostati usando una sintassi di collegamento in cui viene dichiarato solo il nome della proprietà ed 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 a colonne nei livelli della gerarchia.
  • Riferimento sortByColumn in ogni colonna della tabella.
  • Riferimento tabella/colonna/misura in prospettive.

In TMDL i riferimenti vengono eseguiti usando il nome dell'oggetto e seguono gli stessi requisiti di escape e virgolette singole (') che racchiudono 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.columnperspectiveMeasure.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 la notazione punto per fare riferimento a un oggetto, ad esempio: 'Table 1'.'Column 1'

Oggetti figlio

L'albero degli oggetti TOM contiene oggetti figlio in molte posizioni e a livelli diversi. Ad 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 padre costituiscono invece 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 della 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 a più righe dopo l'intestazione della sezione.

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

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, ottengono un'analisi speciale in TMDL. L'intero testo viene letto verbatim perché può includere caratteri speciali come virgolette o parentesi quadre nelle espressioni M o DAX. Le espressioni possono essere a riga multipla o a riga singola. Se multilinea, devono trovarsi nella riga immediatamente dopo la 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 trovarsi all'interno di tale livello di rientro.
  • Tutti gli spazi rientri 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 (```) sono verbatim di lettura, 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 delimitatori backtick (```) è facoltativo e richiesto solo in situazioni univoche. Per la maggior parte delle situazioni, l'uso del rientro corretto e la dichiarazione dell'oggetto garantisce l'analisi corretta di qualsiasi espressione aggiunta alla proprietà.

Quando l'espressione è racchiusa all'interno di backticks, si applicano le regole seguenti:

  • Tutti gli elementi tra tre backticks (```) vengono considerati parte dell'espressione multiblocco e le regole di rientro 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 Expression M
CalculatedPartitionSource Espressione DAX
QueryPartitionSource Query NativeQuery
CalculationItem Espressione DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
Indicatore KPI StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Content 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 oggetto Proprietà predefinita Linguaggio delle espressioni
Misura Espressione DAX
CalculatedColumn Espressione DAX
ComputItem Espressione DAX
FormatStringDefinition Espressione DAX
DetailRowsDefinition Espressione DAX
CalcoloExpression Espressione DAX
DataCoverageDefinition Espressione DAX
TablePermission FilterExpression DAX
ColumnPermission MetadataPermission Enumerazione MetadataPermission
NamedExpression Expression M
MPartitionSource Expression M
CalculatedPartitionSource Espressione DAX
JsonExtendedProperty Valore Json
Annotazione Valore Testo
StringExtendedProperty Valore Testo
DataSource Tipo Enumerazione DataSourceType
Partition SourceType Enumerazione PartitionSourceType
ChangedProperty Proprietà Testo proprietà
ExternalModelRoleMember MemberType Enumerazione RoleMemberType
Qualsiasi proprietà JSON personalizzata (ad esempio DataAccessOptions) Documento JSON Json
LinguisticMetadata Content Json

Descrizioni

TMDL fornisce il supporto di prima classe per le descrizioni. Ai fini della documentazione del modello, la procedura consigliata consiste nel fornire descrizioni per ogni oggetto TOM. TMDL considera le descrizioni come una proprietà speciale con supporto della sintassi esplicita. Seguendo gli esempi di molte altre lingue, le descrizioni vengono specificate in cima a ogni dichiarazione di oggetto usando la sintassi a barre triple (///).

Non è consentito alcun spazio vuoto 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 interrompe le descrizioni degli oggetti in più righe per mantenere le righe del documento generate sotto la lunghezza massima. La lunghezza massima predefinita è di 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 dell'oggetto nello stesso documento. È tuttavia simile alle classi parziali C# in cui è possibile suddividere la definizione dell'oggetto tra più file. Ad esempio, è possibile dichiarare una definizione di tabella in un file [table].tmdl e quindi disporre di 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, dichiarando due misure con lo stesso nome per la stessa tabella in due documenti TMDL diversi, viene generato un errore.

Riferimenti a oggetti

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

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

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Ordinamento della raccolta deterministica

La parola chiave ref viene usata anche per definire e mantenere l'ordinamento della raccolta nei rounding TOM <> TMDL. È particolarmente importante evitare il controllo del codice sorgente sugli oggetti TMDL che vengono serializzati in singoli file: tabelle, ruoli, impostazioni cultura e prospettive. La parola chiave ref viene usata nel file TMDL dell'oggetto padre per dichiarare l'ordine 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 si fa 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:
    • Tutti gli oggetti di raccolta in TOM vengono a cui 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à:

Rientro

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

Ogni oggetto può avere tre livelli di rientro:

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

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 a più righe (table -> measure -> expression).

    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 nel database e negli oggetti figlio diretti del modello perché vengono considerati in modo implicito annidati nel modello radice o nel database:

  • model
  • tabelle
  • espressioni condivise
  • Ruoli
  • cultures
  • prospettive
  • relationships
  • origini dati
  • gruppi di query
  • annotazioni a livello di modello
  • proprietà estese a livello di modello

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

Spazio vuoto

TMDL per impostazione predefinita applica le regole seguenti agli spazi vuoti all'interno dei valori di proprietà ed espressione, se non racchiusi tra 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 degli spazi vuoti vengono tagliate a righe vuote (senza spazi/schede).

Maiuscole/minuscole

Per impostazione predefinita, l'API TMDL in serialize/write usa camelCase, applicata a:

  • Tipi di oggetto
  • Parole chiave
  • Valori di enumerazione

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

Considerazioni e limitazioni

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.