Delen via


TMDL (Tabular Model Definition Language)

Van toepassing op: SQL Server 2016 en hoger Analysis Services Azure Analysis Services Fabric/Power BI Premium

TmDL (Tabular Model Definition Language) is een syntaxis voor objectmodeldefinities voor tabellaire gegevensmodellen op compatibiliteitsniveau 1200 of hoger.

Belangrijke elementen van TMDL zijn:

  • Volledige compatibiliteit met het gehele Tabular Object Model (TOM). Elk TMDL-object bevat dezelfde eigenschappen als TOM.
  • Tekstgebaseerd en geoptimaliseerd voor menselijke interactie en leesbaarheid. TMDL maakt gebruik van een grammaticasyntaxis die vergelijkbaar is met YAML. Elk TMDL-object wordt gerepresenteerd in tekst met minimale scheidingstekens en maakt gebruik van inspringing om ouder-kindrelaties te markeren.
  • Betere bewerkingservaring, met name op eigenschappen met insluitexpressies van verschillende inhoudstypen, zoals DaX (Data Analysis Expression) en M.
  • Beter voor samenwerking vanwege de mapweergave waarbij elk modelobject een afzonderlijke bestandsweergave heeft, waardoor het beter is voor broncodebeheer.

Een belangrijk aspect van TMDL is het gebruik van witruimte-inspringing om een TOM-objectstructuur aan te geven. In het volgende voorbeeld ziet u hoe eenvoudig het is om een tabellair model weer te geven bij het gebruik van 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-mapstructuur

In tegenstelling tot TMSL maakt TMDL gebruik van een mapstructuur. De standaardmapstructuur heeft slechts één niveau van submappen, allemaal met TMDL-bestanden in:

  • Culturen
  • Vooruitzichten
  • roles
  • tables

En root-bestanden voor:

Hier volgt een voorbeeld van een TMDL-map:

TMDL/
├── cultures/
│   ├── en-US.tmdl
│   └── pt-PT.tmdl
├── perspectives/
│   └── perspective1.tmdl
├── roles/
│   ├── role1.tmdl
│   └── role2.tmdl
├── tables/
│   ├── About.tmdl
│   ├── Calendar.tmdl
│   ├── Customer.tmdl
│   ├── Product.tmdl
│   ├── Sales.tmdl
│   └── Store.tmdl
├── relationships.tmdl
├── functions.tmdl
├── expressions.tmdl
├── dataSources.tmdl
├── model.tmdl
└── database.tmdl

Definities zijn onder andere:

  • Eén bestand voor databasedefinitie.
  • Eén bestand voor modeldefinitie.
  • Eén bestand voor alle gegevensbronnen in het model.
  • Eén bestand voor alle expressies in het model.
  • Eén bestand voor alle functies (DAX User Defined Functions in het model.
  • Eén bestand voor alle relaties in het model.
  • Eén bestand voor elk taalkundig cultuurschema.
  • Eén bestand voor elk perspectief.
  • Eén bestand voor elke rol.
  • Eén bestand voor elke tabel.
  • Alle binnenste metagegevenseigenschappen van tabellen (kolom, hiërarchieën, partities,...) bevinden zich in het TMDL-bestand van de bovenliggende tabel.

TMDL-API

Net als bij TMSL (Tabular Model Scripting Language) is er een klasse voor het afhandelen van TMDL-serialisatie. Voor TMDL is de klasse TmdlSerializer, onder de naamruimte Microsoft.AnalysisServices.Tabular .

De TmdlSerializer-klasse biedt methoden voor het serialiseren en deserialiseren van TMDL-documenten:

Serialisatie van mappen

public static void SerializeDatabaseToFolder (Database database, string path)

  • Hiermee ontvangt u een TOM-databaseobject en het TMDL-uitvoerpad.
  • Serialiseert de TOM-database in een TMDL-mapweergave.

Meer informatie over het serialiseren van een map.

public static Database DeserializeDatabaseFromFolder (string path)

  • Hiermee ontvangt u een volledig pad naar een TMDL-map.
  • Retourneert de TOM-databaseobjectweergave van de TMDL-map.

Meer informatie over het deserialiseren van mappen.

String-serialisatie

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

  • Ontvangt een TOM-object en retourneert de TMDL-tekstweergave.

Meer informatie over het serialiseren van een object naar een tekenreeks.

Streamserialisatie

U kunt TMDL serialiseren/deserialiseren naar/van streams, zodat u een TOM-object kunt converteren naar bytestromen voor opslag, verzending en interoperabiliteit tussen platforms. Met de Stream-API kunt u ook bepalen welke TMDL-documenten worden geladen en welke TMDL-documenten worden uitgevoerd.

TMDL Stream-serialisatie wordt verwerkt door de klasse MetadataSerializationContext .

Meer informatie over het serialiseren naar/van TMDL met behulp van streams.

TMDL-taal

Objectdefinitie

Behalve voor serverobject maakt TMDL de volledige TOM Database-objectstructuur beschikbaar in de naamruimte Microsoft.AnalysisServices.Tabular.

Een TMDL-object wordt gedeclareerd door het TOM-objecttype op te geven, gevolgd door de naam. In het volgende codevoorbeeld wordt elk objecttype: model, table, column gevolgd door een objectnaam.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Objecten zoals partition of measurestandaardeigenschappen die kunnen worden toegewezen na het gelijkteken (=) in dezelfde regel van de objectdeclaratie of in de volgende regel voor een expressie met meerdere regels:

table Sales

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

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

De naam van het TMDL-object moet tussen enkele aanhalingstekens (') staan als deze een van de volgende tekens bevat:

  • Punt (.)
  • Is gelijk aan (=)
  • Dubbele punt (:)
  • Enkel aanhalingsteken (')
  • Witruimte ( )

Als een objectnaam enkele aanhalingstekens (') bevat, gebruikt u twee enkele aanhalingstekens om deze te escapen.

Objecteigenschappen

Objecteigenschappen worden opgegeven na de objectdeclaratie of de standaardexpressie van de objecteigenschap met meerdere regels. Objecteigenschapswaarden worden opgegeven na het scheidingsteken dubbele punt (:). Voorbeeld:

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"

De volgende regels zijn van toepassing op eigenschapswaarden:

  • De waarde moet zich op dezelfde regel na de dubbele punt bevinden en mag niet meerdere regels bevatten.

  • Eigenschappen van tekstwaarden

    • Voorloop- en volgdubbele aanhalingstekens zijn optioneel en worden automatisch verwijderd tijdens serialisatie.
    • Moet tussen dubbele aanhalingstekens (") staan als de tekst een volg- of voorloopspaties bevat.
    • Wanneer een waarde tussen dubbele aanhalingstekens staat, en de waarde zelf dubbele aanhalingstekens bevat, gebruikt u twee dubbele aanhalingstekens om deze aanhalingstekens te ontsnappen (zie de displayFolder-eigenschap in het bovenstaande codevoorbeeld).
  • Booleaanse eigenschappen kunnen worden ingesteld met behulp van de syntaxis van het standaardsleutel-waardepaar, zoals met de 'isAvailableInMdx' eigenschap in het vorige voorbeeld. Ze kunnen ook worden ingesteld met behulp van een snelkoppelingsyntaxis waarbij alleen de eigenschapsnaam wordt gedeclareerd en true wordt geïmpliceerd. Zie bijvoorbeeld de eigenschap isHidden in het vorige voorbeeld.

Benoemde objectverwijzingen

Sommige objecteigenschappen bevatten verwijzingen naar andere modelobjecten, bijvoorbeeld:

  • Kolomreferentie in hiërarchieniveaus.
  • sortByColumn-verwijzing in elke tabelkolom.
  • Naslaginformatie voor tabellen/kolommen/metingen in perspectieven.

In TMDL worden verwijzingen gemaakt met behulp van de objectnaam en volgen dezelfde escape- en single-quote (') die vereisten voor objectdeclaratie insluiten. In het volgende codevoorbeeld ziet u objecteigenschappen die een verwijzing naar een ander object bevatten: column.sortByColumn, level.columnen perspectiveMeasure.measureperspectiveTable.table.


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

Als u naar een volledig gekwalificeerde naam wilt verwijzen, gebruikt TMDL punt notatie om te verwijzen naar een object, bijvoorbeeld: 'Table 1'.'Column 1'

Kindobjecten

De TOM-objectstructuur bevat subobjecten op veel verschillende plaatsen en op verschillende niveaus. Voorbeeld:

  • Een modelobject bevat tabel-, rol- en expressieobjecten.
  • Een tabelobject bevat kolom-, meting- en hiërarchieobjecten.

TMDL verklaart subverzamelingen niet expliciet. In plaats daarvan maken alle toepasselijke subelementen binnen het bereik van hun respectieve hoofdonderdeel impliciet deel uit van de elementen van de bijbehorende verzameling. Alle kolomelementen binnen het bereik van een bepaalde tabel worden bijvoorbeeld elementen van de kolommenverzameling van die tabel in TOM, zoals hier wordt weergegeven:

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

Onderliggende objecten hoeven niet aaneengesloten te zijn. U kunt bijvoorbeeld kolommen en metingen declareren in elke volgorde en tussen elkaar.

Standaardeigenschappen

Sommige objecttypen hebben een standaardeigenschap die meestal wordt behandeld als expressies. De standaardeigenschap is objecttypespecifiek. Indien van toepassing, wordt de eigenschapswaarde of expressie opgegeven na de sectiedeclaratie, gevolgd door het gelijkteken (=) als scheidingsteken.

Ondersteunde syntaxis:

  • De waarde wordt opgegeven op dezelfde regel als de sectiekop.
  • De waarde wordt opgegeven als een expressie met meerdere regels na de koptekst van de sectie.

In het volgende codevoorbeeld zijn meting Sales Amount en partitie Sales-Partition1 één regel en meting Quantity meerdere regels:

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

Expressions

Er zijn objecteigenschappen die, hoewel ze een teksteigenschap zijn in TOM, speciale parsing krijgen in TMDL. De hele tekst wordt letterlijk gelezen omdat deze speciale tekens kan bevatten, zoals aanhalingstekens of vierkante haken in M- of DAX-expressies. Expressies kunnen meerdere regels of één regel zijn. Als er meerdere regels zijn, moeten ze zich direct na de eigenschaps- of objectdeclaratie in de regel bevinden.

Een expressiewaarde in TMDL wordt aangegeven met behulp van een gelijkteken (=), zoals in het volgende voorbeeld:

table Table1

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

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

De volgende speciale regels zijn van toepassing op expressies:

  • Expressies met meerdere regels moeten een niveau dieper worden ingesprongen dan de eigenschappen van het bovenliggende object, en de volledige expressie moet binnen dat inspringniveau vallen.
  • Alle buitenste inspringingsspaties worden buiten het ingesprongen niveau van het bovenliggende object verwijderd.
  • Verticale witruimten (lege lijnen zonder witruimten) zijn toegestaan en worden beschouwd als onderdeel van de expressie.
  • Afsluitende lege lijnen en witruimten worden verwijderd.
  • Als u een andere inspringing wilt afdwingen of lege regels of witruimten wilt behouden, gebruikt u de drie backticks (```) die het insluiten.
  • TmDL-serializer plaatst standaard backticks als de expressiewaarde iets bevat dat een wijziging tijdens de roundtrip kan veroorzaken (bijvoorbeeld volgspaties, lege lijnen met witruimten).

Expressies tussen drie backticks (```) worden letterlijk gelezen, inclusief inspringing, lege regels en witte spaties. Het scheidingsteken moet direct na het gelijkteken (=) en de regel na de expressie worden toegepast en mag er niets na hebben, zoals in het volgende voorbeeld:

table Table1

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

            ```

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

Het gebruik van de drie backticks (```) als scheidingstekens is optioneel en alleen vereist in unieke situaties. In de meeste gevallen zorgt het gebruik van de juiste inspringing en objectdeclaratie ervoor dat de expressie die u aan de eigenschap toevoegt, correct wordt geparserd.

Wanneer de expressie tussen backticks staat, zijn de volgende regels van toepassing:

  • Alles tussen drie backticks (```) wordt gezien als deel van de multiblokexpressie en de TMDL-inspringregels worden niet toegepast. Het eindscheidingsteken bepaalt de inspringing binnen de expressie.
  • Relatieve inspringing binnen de expressie wordt behouden. Het eindscheidingsteken (```) bepaalt de linkergrens van de expressie (zie 'Measure1' in het vorige voorbeeld).

De volgende eigenschappen worden behandeld als expressies:

Objecttype Vastgoed Expressietaal
Maatregel Expression DAX
Functie Expression DAX
MPartitionSource Expression M
BerekendePartitieBron Expression DAX
QueryPartitionSource Query NativeQuery
CalculationItem Expression DAX
BasicRefreshPolicy SourceExpressie, PollingExpressie M
KPI StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Content XML of JSON
JsonExtendedProperty Waarde Json
FormatStringDefintion Expression DAX
DataCoverageDefinition Expression DAX
CalculationGroupExpression Expression DAX
NamedExpression Expression DAX
DetailRowsDefinition Expression DAX
TabelToestemming FilterExpression DAX
BerekendeKolom Expression DAX

Standaardeigenschappen per objecttype

In de volgende tabel ziet u de standaardeigenschap en expressietaal per objecttype:

Objectsoort Standaardeigenschap Expressietaal
Maatregel Expression DAX
Functie Expression DAX
BerekendeKolom Expression DAX
CalculationItem Expression DAX
Definitie van FormaatString Expression DAX
DetailRowsDefinition Expression DAX
CalculationExpression Expression DAX
DataCoverageDefinition Expression DAX
TabelToestemming FilterExpression DAX
Kolomtoestemming MetadataPermission MetadataPermission Enum
NamedExpression Expression M
MPartitionSource Expression M
BerekendePartitieBron Expression DAX
JsonExtendedProperty Waarde Json
Aantekening Waarde Tekst
StringExtendedProperty Waarde Tekst
gegevensbron Typologie DataSourceType Enum
Partition Type bron PartitionSourceType Enum
ChangedProperty Vastgoed Eigenschapstekst
ExterneModelRolLid Lid Type RoleMemberType Enum
Een aangepaste JSON-eigenschap (bijvoorbeeld DataAccessOptions) JSON-document Json
LinguisticMetadata Content Json

Beschrijvingen

TMDL biedt eersteklas ondersteuning voor beschrijvingen. Voor modeldocumentatiedoeleinden is het best practice om beschrijvingen te bieden voor elk TOM-object. TMDL behandelt beschrijvingen als een speciale eigenschap met expliciete syntaxisondersteuning. Na de voorbeelden uit vele andere talen worden beschrijvingen boven op elke objectdeclaratie opgegeven met behulp van drievoudige slash (///) syntaxis.

Er is geen witruimte toegestaan tussen het einde van het beschrijvingsblok en het objecttypetoken.

Beschrijvingen kunnen worden gesplitst over meerdere regels. De TMDL-serializer breekt objectbeschrijvingen op in meerdere regels om documentlijnen onder de maximale lengte te houden. De standaard maximumlengte is 80 tekens.

/// Table Description
table Sales

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

Gedeeltelijke aangifte

TMDL dwingt geen objectdeclaratie af in hetzelfde document. Het is echter vergelijkbaar met C#-gedeeltelijke klassen waar het mogelijk is om de objectdefinitie tussen meerdere bestanden te splitsen. U kunt bijvoorbeeld een tabeldefinitie declareren in een [table].tmdl-bestand en vervolgens alle metingen uit alle tabellen hebben gedefinieerd in één [metingen].tmdl-bestand, zoals hier wordt weergegeven:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Om een parseringsfout te voorkomen, kan dezelfde eigenschap niet tweemaal worden gedeclareerd. Het declareren van twee metingen met dezelfde naam voor dezelfde tabel in twee verschillende TMDL-documenten resulteert bijvoorbeeld in een fout.

Objectverwijzingen

U kunt verwijzen naar een ander TMDL-object met behulp van het trefwoord ref gevolgd door het objecttype en de naam.

Als u bijvoorbeeld een kolomobject serialiseert met behulp van de tekenreeksserialisatie-API, is het resultaat:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Volgorde van deterministische verzameling

Het trefwoord ref wordt ook gebruikt om de volgorde van de verzameling op TOM TMDL-rondreizen te definiëren en te behouden. Het is met name belangrijk om bronbeheerverschillen op TMDL-objecten te vermijden die in afzonderlijke bestanden worden geserialiseerd: Tabellen, Rollen, Culturen en Perspectieven. Het trefwoord ref wordt gebruikt in het TMDL-bestand van het bovenliggende object om de volgorde van onderdelen van TOM te declareren.


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'

De volgende regels worden toegepast:

  • Tijdens TMDL-deserialisatie:
    • Objecten waarnaar wordt verwezen in TMDL, maar met ontbrekend TMDL-bestand, worden genegeerd.
    • Objecten waarnaar niet wordt verwezen, maar met een bestaand TMDL-bestand, worden toegevoegd aan het einde van de verzameling.
  • Tijdens TMDL-serialisatie:
    • Naar alle verzamelingsobjecten in TOM wordt verwezen met behulp van het trefwoord ref .
    • Verzamelingen met slechts één item verzenden geen ref.
    • Lege regels worden niet weergegeven tussen referenties van hetzelfde objecttype.

Scheidingstekens voor eigenschapswaarden

Er zijn slechts twee scheidingstekens/symbolen om een eigenschapswaarde toe te wijzen:

  • Is gelijk aan (=)

  • Dubbele punt (:)

Deuk

TMDL maakt gebruik van strikte witruimte-inspringingsregels om de structuur van de TOM-hiërarchie aan te geven. Een TMDL-document maakt gebruik van een standaardregel met een enkele tab inspringing.

Elk object kan drie niveaus van inspringing hebben:

  • Niveau 1 - Objectdeclaratie
    • Niveau 2 - Objecteigenschappen
      • Niveau 3 - Multi-line expressies voor objecteigenschappen

In een TMDL-document wordt inspringing toegepast in de volgende gevallen:

  • Tussen een objectsectiekop en de eigenschappen van het object (tabel -> eigenschappen).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Tussen een object en zijn onderliggende objecten (tabel -> metingen).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Tussen een object en zijn meerregelige expressies (tabel -> maat -> expressie).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Expressies met meerdere regels moeten één niveau dieper worden ingesprongen dan objecteigenschappen en de volledige expressie moet zich binnen dat inspringingsniveau bevinden (zie expressies).

Database- en directe onderliggende objecten van model hoeven niet te worden ingesprongen, omdat ze impliciet zijn genest onder het hoofdmodel of de database:

  • model
  • tables
  • gedeelde expressies
  • roles
  • Culturen
  • Vooruitzichten
  • relaties
  • Gegevensbronnen
  • querygroepen
  • aantekeningen op modelniveau
  • uitgebreide eigenschappen op modelniveau

Als u deze regels voor inspringing niet volgt, ontstaat er een parseerfout.

Spatie

TMDL past standaard de volgende regels toe op witruimte binnen eigenschaps- en expressie-waarden, wanneer deze niet tussen backticks (```) of dubbele aanhalingstekens (") staan:

  • Bij eigenschapswaarden worden voorloop- en volgspaties bijgesneden.
  • Bij expressies worden witruimtelijnen aan het einde van expressies verwijderd.
  • Witruimtelijnen worden afgekapt tot lege lijnen (geen spaties/tabs).

Behuizing

TmDL-API voor serialiseren/schrijven maakt standaard gebruik van camelCase, toegepast op:

  • Objecttypen
  • Zoekwoorden
  • Opsommingswaarden

Bij het deserialiseren/lezen is de TMDL-API niet hoofdlettergevoelig.

Nu u kennis hebt van TMDL, moet u Aan de slag met TMDL zien om te leren hoe u een TMDL-modelweergave van een semantisch Power BI-model kunt krijgen en implementeren.