Udostępnij przez


Tabelaryczny język definicji modelu (TMDL)

Dotyczy: SQL Server 2016 i nowsze usługi Analysis Services Azure Analysis Services Fabric/Power BI Premium

Tabelaryczny język definicji modelu (TMDL) to składnia definicji modelu obiektów dla modeli danych tabelarycznych na poziomie zgodności 1200 lub wyższym.

Kluczowe elementy języka TMDL obejmują:

  • Pełna zgodność z całym modelem obiektów tabelarycznych (TOM). Każdy obiekt TMDL uwidacznia te same właściwości co TOM.
  • Oparte na tekście i zoptymalizowane pod kątem interakcji i czytelności człowieka. Język TMDL używa składni gramatycznej podobnej do języka YAML. Każdy obiekt TMDL jest reprezentowany w tekście z minimalnymi ogranicznikami i używa wcięcia do oznaczania relacji nadrzędno-podrzędnych.
  • Lepsze środowisko edycji, szczególnie we właściwościach z wyrażeniami osadzonymi z różnych rodzajów zawartości, takich jak Data Analysis Expressions (DAX) i M.
  • Lepsza współpraca ze względu na reprezentację folderu, w której każdy obiekt modelu ma indywidualną reprezentację pliku, dzięki czemu jest bardziej przyjazny dla kontroli źródła.

Ważnym aspektem języka TMDL jest korzystanie z wcięć białych znaków w celu oznakowania struktury obiektu TOM. W poniższym przykładzie pokazano, jak łatwo jest reprezentować model tabelaryczny podczas korzystania z języka 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]

Struktura folderów TMDL

W przeciwieństwie do języka TMSL język TMDL używa struktury folderów. Domyślna struktura folderów ma tylko jeden poziom podfolderów— wszystkie z plikami tmdl wewnątrz:

  • Kultur
  • Perspektywy
  • roles
  • tables

Pliki główne dla:

Oto przykład folderu TMDL:

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

Definicje obejmują:

  • Jeden plik definicji bazy danych.
  • Jeden plik definicji modelu.
  • Jeden plik dla wszystkich źródeł danych w modelu.
  • Jeden plik dla wszystkich wyrażeń w modelu.
  • Jeden plik dla wszystkich funkcji (funkcje zdefiniowane przez użytkownika języka DAX w modelu).
  • Jeden plik dla wszystkich relacji w modelu.
  • Jeden plik dla każdego schematu językowego kultury.
  • Jeden plik dla każdej perspektywy.
  • Jeden plik dla każdej roli.
  • Jeden plik dla każdej tabeli.
  • Wszystkie wewnętrzne właściwości metadanych tabel (Kolumna, Hierarchie, Partycje,...) są przechowywane w pliku TMDL tabeli nadrzędnej.

TMDL API

Podobnie jak w przypadku języka TMSL (Tabular Model Scripting Language) istnieje klasa do obsługi serializacji TMDL. W przypadku języka TMDL klasa to TmdlSerializer w obszarze przestrzeni nazw Microsoft.AnalysisServices.Tabular .

Klasa TmdlSerializer uwidacznia metody serializacji i deserializacji dokumentów TMDL:

Serializacja folderów

public static void SerializeDatabaseToFolder (Database database, string path)

  • Odbiera obiekt bazy danych TOM i ścieżkę wyjściową TMDL.
  • Serializuje bazę danych TOM w reprezentacji folderu TMDL.

Dowiedz się więcej na temat serializowania do folderu.

public static Database DeserializeDatabaseFromFolder (string path)

  • Odbiera pełną ścieżkę do folderu TMDL.
  • Zwraca reprezentację obiektu bazy danych TOM folderu TMDL.

Dowiedz się więcej na temat deserializacji z folderów.

Serializacja ciągów

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

  • Odbiera obiekt TOM i zwraca jego reprezentację tekstu TMDL.

Dowiedz się więcej na temat serializowania obiektu w ciąg znaków.

Serializacja strumienia

Można serializować/deserializować TMDL do/z strumieni, co pozwala przekonwertować obiekt TOM na strumienie bajtów na potrzeby magazynowania, transmisji i współdziałania między platformami. Interfejs API strumienia umożliwia również kontrolowanie, które dokumenty TMDL są ładowane i które dokumenty TMDL są wyprowadzane.

Serializacja strumienia TMDL jest obsługiwana przez klasę MetadataSerializationContext .

Dowiedz się więcej jak serializować do/z TMDL za pomocą strumieni.

Język TMDL

Deklaracja obiektu

Z wyjątkiem obiektu Serwera język TMDL uwidacznia całe drzewo obiektów bazy danych TOM w przestrzeni nazw Microsoft.AnalysisServices.Tabular.

Obiekt TMDL jest zadeklarowany przez określenie typu obiektu TOM, po którym następuje jego nazwa. W poniższym przykładzie kodu po każdym typie obiektu: model, table, column następuje nazwa obiektu.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Obiekty takie jak partition lub measure mają właściwości domyślne , które można przypisać po ograniczniku równości (=) w tym samym wierszu deklaracji obiektu lub w następującym wierszu wyrażenia wielowierszowego:

table Sales

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

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

Nazwa obiektu TMDL musi być ujęta w apostrofy ('), jeśli zawiera którykolwiek z następujących znaków:

  • Kropka (.)
  • Równa się (=)
  • Dwukropek (:)
  • Pojedynczy cudzysłów (')
  • Białe znaki ( )

Jeśli nazwa obiektu zawiera apostrofy ('), użyj dwóch pojedynczych cudzysłowów, aby go uniknąć.

Właściwości obiektu

Właściwości obiektu są określane po deklaracji obiektu lub po domyślnym wyrażeniu obiektu wielowierszowego. Wartości właściwości obiektu są określane po dwukropku jako ograniczniku (:). Przykład:

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"

Następujące reguły dotyczą wartości właściwości:

  • Wartość musi znajdować się w tym samym wierszu po dwukropku i nie może zawierać wielu wierszy.

  • Wartości właściwości tekstowych

    • Podwójne cudzysłowy na początku i końcu są opcjonalne i automatycznie usuwane podczas serializacji.
    • Musi być ujęta w cudzysłowy ("), jeśli tekst zawiera końcowe lub przednie puste miejsca.
    • Kiedy wartość jest zamknięta w cudzysłowach podwójnych, jeśli zawiera ona cudzysłowy podwójne, użyj dwóch podwójnych cudzysłowów, aby je zniwelować (zobacz właściwość displayFolder w powyższym przykładzie kodu).
  • Właściwości Booleanowskie można ustawić przy użyciu standardowej składni pary klucz/wartość, tak jak w przypadku właściwości 'isAvailableInMdx' w poprzednim przykładzie. Można je również ustawić przy użyciu skróconej składni, w której zadeklarowana jest tylko nazwa właściwości, a true jest implikowane. Zobacz na przykład właściwość "isHidden" w poprzednim przykładzie.

Odwołania do nazwanych obiektów

Niektóre właściwości obiektu przechowują odwołania do innych obiektów modelu, na przykład:

  • Odwołanie do kolumn na poziomach hierarchii.
  • odwołanie sortByColumn w każdej kolumnie tabeli.
  • Odwołanie do tabeli/kolumny/miary w perspektywach.

W języku TMDL odwołania są tworzone przy użyciu nazwy obiektu i są zgodne z tymi samymi ucieczkami i pojedynczym cudzysłowem (') otaczającymi wymagania deklaracji obiektu. W poniższym przykładzie kodu zobaczysz właściwości obiektu, które przechowują odwołanie do innego obiektu: column.sortByColumn, level.columnperspectiveMeasure.measurei perspectiveTable.table.


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

W razie potrzeby odwołania się do w pełni kwalifikowanej nazwy język TMDL używa notacji kropkowej do odwołowywania się do obiektu, na przykład: 'Table 1'.'Column 1'

Obiekty podrzędne

Drzewo obiektów TOM zawiera obiekty podrzędne w wielu miejscach i na różnych poziomach. Przykład:

  • Obiekt modelu zawiera obiekty tabel, ról i wyrażeń.
  • Obiekt tabeli zawiera obiekty kolumn, miary i hierarchii.

TMDL nie deklaruje jawnie dziecięcych kolekcji. Zamiast tego wszystkie odpowiednie elementy podrzędne w zakresie odpowiedniego elementu nadrzędnego niejawnie składają się na elementy odpowiedniej kolekcji. Na przykład wszystkie elementy kolumn w zakresie określonej tabeli stają się elementami kolekcji kolumn tej tabeli w narzędziu TOM, jak pokazano tutaj:

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

Obiekty podrzędne nie muszą być przylegające. Na przykład, można zadeklarować kolumny i miary w dowolnej kolejności, mieszając je.

Właściwości domyślne

Niektóre typy obiektów mają właściwość domyślną, która w większości przypadków jest traktowana jak wyrażenia. Właściwość domyślna jest specyficzna dla typu obiektu. Jeśli ma to zastosowanie, wartość właściwości lub wyrażenie jest określane po ograniczniku równości (=) — po deklaracji sekcji.

Obsługiwana składnia:

  • Wartość jest określona w tym samym wierszu co nagłówek sekcji.
  • Wartość jest określana jako wyrażenie wielowierszowe po nagłówku sekcji.

W poniższym przykładzie kodu, miara Sales Amount i partycja Sales-Partition1 są jednolinijkowe, a miara Quantity jest wielowierszowa.

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

Istnieją właściwości obiektu, które podczas bycia właściwością tekstową w narzędziu TOM uzyskują specjalne analizowanie w języku TMDL. Cały tekst jest odczytywany dosłownie, ponieważ może zawierać znaki specjalne, takie jak cudzysłowy lub nawiasy kwadratowe w wyrażeniach języka M lub DAX. Wyrażenia mogą być wielowierszowe lub jednowierszowe. Jeśli są wielowierszowe, muszą być umieszczone w wierszu bezpośrednio po deklaracji właściwości lub obiektu.

Wartość wyrażenia w języku TMDL jest określona po znaku równości (=), tak jak w poniższym przykładzie:

table Table1

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

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

Do wyrażeń mają zastosowanie następujące specjalne reguły:

  • Wyrażenia wielowierszowe muszą być wcięte na jednym poziomie głębiej do właściwości obiektu nadrzędnego, a całe wyrażenie musi znajdować się na tym poziomie wcięcia.
  • Wszystkie zewnętrzne białe znaki wcięcia są usuwane poza poziom wcięcia obiektu nadrzędnego.
  • Odstępy pionowe (puste wiersze bez białych znaków) są dozwolone i są uznawane za część wyrażenia.
  • Końcowe puste wiersze i białe znaki są usuwane.
  • Aby wymusić inne wcięcie lub zachować końcowe puste wiersze lub białe znaki, otocz je trzema backtickami (```).
  • Domyślnie serializator TMDL będzie ujęty w backticksy, jeśli wartość wyrażenia zawiera coś, co może spowodować modyfikację w obie strony (na przykład końcowe białe znaki, puste wiersze z białymi znakami).

Wyrażenia ujęte w trzy backticks (```) są odczytywane dosłownie, w tym wcięcia, puste wiersze i białe znaki. Ogranicznik powinien być stosowany bezpośrednio po znaku równości (=) i wierszu po wyrażeniu i nie może mieć żadnych elementów po nim, jak w poniższym przykładzie:

table Table1

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

            ```

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

Użycie trzech ograniczników (```) jest opcjonalne i wymagane tylko w unikatowych sytuacjach. W większości sytuacji użycie poprawnego wcięcia i deklaracji obiektu zapewnia poprawne analizowanie dowolnego wyrażenia dodanego do właściwości.

Gdy wyrażenie jest ujęte w backticks, obowiązują następujące reguły:

  • Wszystkie elementy między trzema backticks (```) są uznawane za część wyrażenia wieloblokowego i reguły wcięcia TMDL nie są stosowane. Ogranicznik końcowy określa wcięcie w wyrażeniu.
  • Względne wcięcie w wyrażeniu jest zachowywane. Ogranicznik końcowy (```) określa lewą granicę wyrażenia (zobacz "Measure1" w poprzednim przykładzie).

Następujące właściwości są traktowane jako wyrażenia:

Typ obiektu Majątek Język wyrażeń
Mierzenie Expression DAX
Funkcja Expression DAX
MPartitionSource Expression M
ŹródłoObliczanejPartycji Expression DAX
QueryPartitionSource Query Zapytanie natywne
Element obliczeniowy Expression DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
KPI StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Content XML lub Json
JsonExtendedProperty Wartość Json
FormatStringDefintion Expression DAX
DefinicjaZakresuDanych Expression DAX
CalculationGroupExpression Expression DAX
NazwaneWyrażenie Expression DAX
DetailRowsDefinition Expression DAX
UprawnieniaTabeli FilterExpression DAX
Kolumna obliczeniowa Expression DAX

Domyślne właściwości według typu obiektu

W poniższej tabeli przedstawiono domyślną właściwość i język wyrażeń według typu obiektu:

Typ obiektu Właściwość domyślna Język wyrażeń
Mierzenie Expression DAX
Funkcja Expression DAX
Kolumna obliczeniowa Expression DAX
Element obliczeniowy Expression DAX
FormatStringDefinition Expression DAX
DetailRowsDefinition Expression DAX
ObliczenieWyrażenie Expression DAX
DefinicjaZakresuDanych Expression DAX
UprawnieniaTabeli FilterExpression DAX
UprawnienieKolumny Uprawnienia do metadanych Enum MetadataPermission
NazwaneWyrażenie Expression M
MPartitionSource Expression M
ŹródłoObliczanejPartycji Expression DAX
JsonExtendedProperty Wartość Json
Adnotacja Wartość Tekst
StringExtendedProperty Wartość Tekst
Źródło danych Typ Wyliczenie DataSourceType
Partition Typ źródła PartitionSourceType, typ wyliczeniowy
ZmienionaWłaściwość Majątek Tekst właściwości
ExternalModelRoleMember Typ członka RoleMemberType Enum
Dowolna niestandardowa właściwość JSON (na przykład DataAccessOptions) Dokument JSON Json
LinguisticMetadata Content Json

Opisy

TMDL zapewnia pierwszorzędne wsparcie dla opisów. W celach dokumentacji modelu najlepszym rozwiązaniem jest podanie opisów dla każdego obiektu TOM. TMDL traktuje opisy jako specjalną właściwość z wyraźną obsługą składni. Zgodnie z przykładami z wielu innych języków opisy są określane na początku każdej deklaracji obiektu przy użyciu składni potrójnego ukośnika (///).

Odstęp między końcem bloku opisu a tokenem typu obiektu nie jest dozwolony.

Opisy można podzielić na wiele wierszy. Serializator TMDL dzieli opisy obiektów na wiele wierszy, aby zachować emitowane wiersze dokumentu pod maksymalną długością. Domyślna maksymalna długość to 80 znaków.

/// Table Description
table Sales

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

Deklaracja częściowa

TMDL nie wymusza deklaracji obiektu tym samym dokumentem. Jest to jednak podobne do klas częściowych języka C# , w których można podzielić definicję obiektu między wiele plików. Można na przykład zadeklarować definicję tabeli w pliku [table].tmdl, a następnie wszystkie miary ze wszystkich tabel zdefiniowane w jednym pliku [measures].tmdl, jak widać poniżej:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Aby uniknąć błędu analizy, nie można zadeklarować dwukrotnie tej samej właściwości. Na przykład deklarowanie dwóch miar o tej samej nazwie dla tej samej tabeli w dwóch różnych dokumentach TMDL powoduje wystąpienie błędu.

Odwołania do obiektów

Możesz odwołać się do innego obiektu TMDL przy użyciu słowa kluczowego ref , po którym następuje typ obiektu i nazwa.

Na przykład, jeśli zserializujesz obiekt Column przy użyciu API serializacji tekstu, wynik będzie:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Określanie kolejności kolekcji deterministycznej

Słowo kluczowe ref jest również używane do definiowania i zachowywania kolejności kolekcji na transakcjach TOM i TMDL <>. Szczególnie ważne jest, aby uniknąć różnic kontroli źródła w obiektach TMDL, które są serializowane w poszczególnych plikach: tabele, role, kultury i perspektywy. Słowo kluczowe ref jest używane w pliku TMDL obiektu nadrzędnego do deklarowania kolejności elementów według 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'

Stosowane są następujące reguły:

  • Podczas deserializacji TMDL:
    • Obiekty odwołujące się do TMDL, ale bez powiązanego pliku TMDL, są ignorowane.
    • Obiekty, które nie są przywoływane, ale mają istniejący plik TMDL, są dołączane na końcu kolekcji.
  • Podczas serializacji TMDL:
    • Wszystkie obiekty kolekcji w TOM są odwoływane przy użyciu słowa kluczowego ref.
    • Kolekcje z tylko jednym elementem nie emitują odwołania.
    • Puste wiersze nie są emitowane między referencjami, jeśli mają tego samego typu obiekt.

Ograniczniki wartości właściwości

Do przypisania wartości właściwości istnieją tylko dwa ograniczniki/symbole:

  • Równa się (=)

  • Dwukropek (:)

    • Używany dla każdej wartości właściwości, która nie jest wyrażeniem. Uwzględnianie właściwości zawierających odwołania do modelu.

Wcięcie

Język TMDL używa ścisłych reguł wcięcia odstępów do oznaczania struktury hierarchii TOM. Dokument TMDL używa domyślnej reguły wcięcia pojedynczego tabulatora .

Każdy obiekt może mieć trzy poziomy wcięcia:

  • Poziom 1 — deklaracja obiektu
    • Poziom 2 — właściwości obiektu
      • Poziom 3 — wyrażenia wielowierszowe właściwości obiektu

W dokumencie TMDL wcięcie jest stosowane w następujących przypadkach:

  • Między nagłówkiem sekcji obiektu a właściwościami obiektu (tabela —> właściwości).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Między obiektem a jego obiektami podrzędnymi (tabela —> miary).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Między obiektem a wyrażeniami wielowierszowymi (tabela —> miara —> wyrażenie).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Wyrażenia wielowierszowe muszą być wcięte o jeden poziom głębiej niż właściwości obiektu, a całe wyrażenie musi znajdować się w ramach tego poziomu wcięcia (zobacz wyrażenia).

Nie trzeba stosować wcięć dla obiektów baz danych i bezpośrednich obiektów podrzędnych modelu, ponieważ są one niejawnie traktowane jako zagnieżdżone w głównym Modelu lub Bazie Danych.

  • model
  • tables
  • wyrażenia udostępnione
  • roles
  • Kultur
  • Perspektywy
  • Relacje
  • źródła danych
  • grupy zapytań
  • adnotacje na poziomie modelu
  • właściwości rozszerzone na poziomie modelu

Niezastosowanie się do tych reguł wcięcia powoduje błąd analizy.

Znak odstępu

Domyślnie TMDL stosuje następujące reguły do białych znaków w wartościach właściwości i wyrażeń, jeśli nie są objęte apostrofami (```) lub cudzysłowami ("):

  • W przypadku wartości właściwości spacje przed i za są przycinane.
  • W wyrażeniach linie odstępów na końcu wyrażeń są porzucane.
  • Linie białych znaków są usuwane do pustych wierszy (tj. bez spacji/tabulacji).

Obudowa

Domyślnie interfejs API TMDL przy serializacji/zapisie używa camelCase, stosowane do:

  • Typy obiektów
  • Słowa kluczowe
  • Wartości wyliczenia

Interfejs API TMDL podczas deserializacji/odczytu nie uwzględnia wielkości liter.

Teraz, gdy znasz język TMDL, zobacz Wprowadzenie do języka TMDL , aby dowiedzieć się, jak uzyskać i wdrożyć reprezentację modelu TMDL w modelu semantycznym usługi Power BI.