Bahasa Definisi Model Tabular (TMDL)

Berlaku untuk: SQL Server 2016 dan yang lebih baru Analysis Services Azure Analysis Services Fabric/Power BI Premium

Penting

Bahasa Definisi Model Tabular (TMDL) saat ini dalam pratinjau. Saat dalam pratinjau, fungsionalitas dan dokumentasi cenderung berubah.

Tabular Model Definition Language (TMDL) adalah sintaks definisi model objek untuk model data tabular pada tingkat kompatibilitas 1200 atau lebih tinggi.

Elemen kunci TMDL meliputi:

  • Kompatibilitas penuh dengan seluruh Model Objek Tabular (TOM). Setiap objek TMDL mengekspos properti yang sama dengan TOM.
  • Berbasis teks dan dioptimalkan untuk interaksi dan keterbacaan manusia. TMDL menggunakan sintaks tata bahasa yang mirip dengan YAML. Setiap objek TMDL diwakili dalam teks dengan pemisah minimal dan menggunakan indentasi untuk menandai hubungan induk-anak.
  • Pengalaman pengeditan yang lebih baik, terutama pada properti dengan ekspresi semat dari berbagai jenis konten, seperti Ekspresi Analisis Data (DAX) dan M.
  • Lebih baik untuk kolaborasi karena representasi foldernya di mana setiap objek model memiliki representasi file individual, membuatnya lebih ramah kontrol sumber.

Aspek penting dari TMDL adalah penggunaan indentasi spasi kosong untuk menunjukkan struktur objek TOM. Contoh berikut menunjukkan betapa mudahnya mewakili model tabular saat menggunakan 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]

Struktur folder TMDL

Tidak seperti TMSL, TMDL menggunakan struktur folder. Struktur folder default hanya memiliki satu tingkat sub-folder, semuanya dengan file .tmdl di dalamnya:

  • budaya
  • Perspektif
  • peran
  • tabel

Dan file akar untuk:

  • database
  • model
  • hubungan
  • Ekspresi
  • Datasources

Berikut adalah contoh folder TMDL:

Folder dengan representasi TMDL dari model

Definisi meliputi:

  • Satu file untuk definisi database.
  • Satu file untuk definisi model.
  • Satu file untuk semua sumber data dalam model.
  • Satu file untuk semua ekspresi dalam model.
  • Satu file untuk semua hubungan dalam model.
  • Satu file untuk setiap skema linguistik budaya.
  • Satu file untuk setiap perspektif.
  • Satu file untuk setiap peran.
  • Satu file untuk setiap tabel.
  • Semua properti metadata dalam tabel (Metadata Kolom, Hierarki, Partisi,...) berada di file TMDL tabel induk.

TMDL API

Mirip dengan Tabular Model Scripting Language (TMSL), ada kelas untuk menangani Serialisasi TMDL. Untuk TMDL, kelasnya adalah TmdlSerializer, di bawah namespace Microsoft.AnalysisServices.Tabular .

Kelas TmdlSerializer memaparkan metode untuk menserialisasikan dan mendeserialisasi dokumen TMDL:

Serialisasi Folder

public static void SerializeDatabaseToFolder (Database database, string path)

  • Menerima objek database TOM dan jalur output TMDL.
  • Menserialisasikan database TOM ke dalam representasi folder TMDL.

Pelajari selengkapnya tentang cara membuat serialisasi ke folder.

public static Database DeserializeDatabaseFromFolder (string path)

  • Menerima jalur lengkap ke folder TMDL.
  • Mengembalikan representasi objek database TOM dari folder TMDL.

Pelajari selengkapnya tentang cara mendeserialisasi dari folder.

Serialisasi String

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

  • Menerima objek TOM dan mengembalikan representasi teks TMDL-nya.

Pelajari selengkapnya tentang cara menserialisasikan objek ke string.

Serialisasi Aliran

Anda dapat membuat serialisasi/mendeserialisasi TMDL ke/dari aliran, memungkinkan Anda mengonversi objek TOM menjadi aliran byte untuk penyimpanan, transmisi, dan interoperabilitas di seluruh platform. Stream API juga memungkinkan Anda mengontrol dokumen TMDL mana yang dimuat dan dokumen TMDL mana yang dihasilkan.

Serialisasi Aliran TMDL ditangani oleh kelas MetadataSerializationContext .

Pelajari selengkapnya tentang cara membuat serialisasi ke/dari TMDL menggunakan aliran.

Bahasa TMDL

Deklarasi objek

Kecuali untuk objek Server, TMDL mengekspos seluruh pohon objek Database TOM di namespace Microsoft.AnalysisServices.Tabular.

Objek TMDL dideklarasikan dengan menentukan jenis objek TOM diikuti dengan namanya. Dalam contoh kode berikut, setiap jenis objek: model, table, column diikuti dengan nama objek.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Objek seperti partition atau measure memiliki properti default yang dapat ditetapkan setelah pemisah sama dengan (=) di baris deklarasi objek yang sama atau di baris berikut untuk ekspresi multibaris:

table Sales

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

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

Nama objek TMDL harus diapit dalam tanda kutip tunggal (') jika menyertakan salah satu karakter berikut:

  • Titik (.)
  • Sama dengan (=)
  • Titik dua (:)
  • Kutipan Tunggal (')
  • Spasi kosong ( )

Jika nama objek berisi tanda kutip tunggal ('), gunakan dua tanda kutip tunggal untuk menghindarinya.

Properti Obyek

Properti objek ditentukan setelah deklarasi objek atau ekspresi multi-baris properti default objek. Nilai properti objek ditentukan setelah pemisah titik dua (:). Contohnya:

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"

Aturan berikut berlaku untuk nilai properti:

  • Nilai harus berada di baris yang sama setelah titik dua dan tidak boleh memiliki beberapa baris.

  • Nilai properti teks

    • Tanda kutip Ganda di awal dan akhir bersifat opsional dan otomatis dilucuti selama serialisasi.
    • Harus diapit dalam tanda kutip ganda (") jika teks berisi spasi kosong di belakang atau di awal.
    • Saat diapit tanda kutip ganda, jika nilai berisi tanda kutip ganda, gunakan dua tanda kutip ganda untuk menghindarinya (lihat displayFolder properti dalam contoh kode di atas).
  • Properti Boolean dapat diatur dengan menggunakan sintaks pasangan kunci/nilai standar, seperti dengan 'isAvailableInMdx' properti dalam contoh sebelumnya. Mereka juga dapat diatur dengan menggunakan sintaks pintasan di mana hanya nama properti yang dideklarasikan dan true tersirat. Lihat, misalnya, properti 'isHidden' dalam contoh sebelumnya.

Referensi objek bernama

Beberapa properti objek menyimpan referensi ke objek model lain, misalnya:

  • Referensi kolom dalam tingkat hierarki.
  • referensi sortByColumn di setiap kolom tabel.
  • Referensi tabel/kolom/pengukuran dalam perspektif.

Dalam TMDL, referensi dibuat menggunakan nama objek dan mengikuti persyaratan pelepasan dan tanda kutip tunggal (') yang sama yang mencakup persyaratan deklarasi objek. Dalam contoh kode berikut, Anda akan melihat properti objek yang menyimpan referensi ke objek lain: column.sortByColumn, level.column, perspectiveMeasure.measure dan perspectiveTable.table.


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

Jika diperlukan untuk mereferensikan nama yang sepenuhnya memenuhi syarat, TMDL menggunakan notasi titik untuk mereferensikan objek, misalnya: 'Table 1'.'Column 1'

Objek anak

Pohon objek TOM berisi objek anak di banyak tempat dan pada tingkat yang berbeda. Contohnya:

  • Objek model berisi objek tabel, peran, dan ekspresi.
  • Objek tabel berisi objek kolom, pengukuran, dan hierarki.

TMDL tidak mendeklarasikan koleksi anak secara eksplisit. Sebaliknya, semua elemen anak yang berlaku dalam cakupan induk masing-masing secara implisit membentuk elemen koleksi yang sesuai. Misalnya, semua elemen kolom dalam cakupan tabel tertentu menjadi elemen kumpulan kolom tabel tersebut di TOM, seperti yang diperlihatkan di sini:

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

Objek anak tidak harus berseberangan. Misalnya, Anda dapat mendeklarasikan kolom dan pengukuran dalam urutan dan intermingled apa pun.

Properti default

Beberapa jenis objek memiliki properti default yang sebagian besar waktu diperlakukan seperti ekspresi. Properti default adalah jenis objek tertentu. Jika berlaku, nilai atau ekspresi properti ditentukan setelah pemisah sama dengan (=) - setelah deklarasi bagian.

Sintaksis yang didukung:

  • Nilai ditentukan pada baris yang sama dengan header bagian.
  • Nilai ditentukan sebagai ekspresi multibaris mengikuti header bagian.

Dalam contoh kode berikut, pengukuran Sales Amount dan partisi Sales-Partition1 adalah baris tunggal dan pengukuran Quantity adalah multibaris:

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

Ada properti objek yang, saat menjadi properti teks di TOM, mendapatkan penguraian khusus di TMDL. Seluruh teks dibaca secara verbatim karena dapat menyertakan karakter khusus seperti tanda kutip atau kurung siku dalam ekspresi M atau DAX. Ekspresi bisa berupa multibaris atau satu baris. Jika multibaris, mereka harus berada di baris segera setelah deklarasi properti atau objek.

Nilai ekspresi di TMDL ditentukan setelah pemisah yang sama dengan (=), seperti dalam contoh berikut:

table Table1

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

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

Aturan khusus berikut berlaku untuk ekspresi:

  • Ekspresi multibaris harus diindentasi satu tingkat lebih dalam ke properti objek induk dan seluruh ekspresi harus berada dalam tingkat indentasi tersebut.
  • Semua spasi kosong indentasi luar dilucuti di luar tingkat inden objek induk.
  • Spasi putih vertikal (garis kosong tanpa spasi kosong) diperbolehkan dan dianggap sebagai bagian dari ekspresi.
  • Baris kosong dan spasi kosong berikutnya akan dihapus.
  • Untuk memberlakukan indentasi yang berbeda atau untuk mempertahankan garis kosong atau spasi kosong berikutnya, gunakan tiga backtick (```) yang diapit.
  • Secara default, serializer TMDL akan diapit dengan backtick jika nilai ekspresi berisi apa pun yang dapat menyebabkan modifikasi pada roundtrip (misalnya, spasi kosong di belakang, baris kosong dengan spasi kosong).

Ekspresi yang diapit dengan tiga backtick (```) dibaca verbatim termasuk indentasi, baris kosong, dan spasi kosong. Pemisah harus diterapkan segera setelah tanda sama dengan (=) dan baris yang mengikuti ekspresi dan tidak boleh memiliki apa pun setelahnya, seperti dalam contoh berikut:

table Table1

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

            ```

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

Menggunakan tiga pemisah backticks (```) bersifat opsional dan hanya diperlukan dalam situasi unik. Untuk sebagian besar situasi, menggunakan indentasi dan deklarasi objek yang benar memastikan penguraian ekspresi apa pun yang Anda tambahkan ke properti .

Saat ekspresi diapit dalam backtick, aturan berikut berlaku:

  • Semuanya antara tiga backtick (```) dianggap sebagai bagian dari ekspresi multi-blok dan aturan indentasi TMDL tidak diterapkan. Pemisah akhir menentukan indentasi dalam ekspresi.
  • Indentasi relatif dalam ekspresi dipertahankan. Pemisah akhir (```) menentukan batas kiri ekspresi (lihat 'Measure1' di contoh sebelumnya).

Properti berikut diperlakukan sebagai ekspresi:

Jenis Objek Properti Bahasa pemograman ekspresi
Ukuran Ekspresi DAX
MPartitionSource Ekspresi M
CalculatedPartitionSource Ekspresi DAX
QueryPartitionSource Kueri NativeQuery
CalculationItem Ekspresi DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
KPI StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Konten XML atau Json
JsonExtendedProperty Nilai Json
FormatStringDefintion Ekspresi DAX
DataCoverageDefinition Ekspresi DAX
CalculationGroupExpression Ekspresi DAX
NamedExpression Ekspresi DAX
DetailRowsDefinition Ekspresi DAX
TablePermission FilterExpression DAX
CalculatedColumn Ekspresi DAX

Properti default menurut jenis objek

Tabel berikut ini memperlihatkan properti default dan bahasa ekspresi menurut jenis objek:

Tipe objek Properti default Bahasa pemograman ekspresi
Ukuran Ekspresi DAX
CalculatedColumn Ekspresi DAX
CalculationItem Ekspresi DAX
FormatStringDefinition Ekspresi DAX
DetailRowsDefinition Ekspresi DAX
CalculationExpression Ekspresi DAX
DataCoverageDefinition Ekspresi DAX
TablePermission FilterExpression DAX
Pemisahan Kolom MetadataPermission MetadataPermission Enum
NamedExpression Ekspresi M
MPartitionSource Ekspresi M
CalculatedPartitionSource Ekspresi DAX
JsonExtendedProperty Nilai Json
Anotasi Nilai Teks
StringExtendedProperty Nilai Teks
DataSource Jenis DataSourceType Enum
Partisi SourceType PartitionSourceType Enum
ChangedProperty Properti Teks Properti
ExternalModelRoleMember MemberType RoleMemberType Enum
Properti JSON Kustom apa pun (misalnya, DataAccessOptions) Documen JSON Json
LinguisticMetadata Konten Json

Deskripsi

TMDL menyediakan dukungan kelas satu untuk deskripsi. Untuk tujuan dokumentasi model, praktik terbaik adalah memberikan deskripsi untuk setiap objek TOM. TMDL memperlakukan deskripsi sebagai properti khusus dengan dukungan sintaksis eksplisit. Mengikuti contoh dari banyak bahasa lain, deskripsi ditentukan di atas setiap deklarasi objek menggunakan sintaks tiga garis miring (///).

Tidak ada spasi kosong yang diizinkan antara blok deskripsi akhir dan token jenis objek.

Deskripsi dapat dibagi di beberapa baris. Serializer TMDL memecah deskripsi objek menjadi beberapa baris untuk menjaga baris dokumen yang dipancarkan di bawah panjang maksimum. Panjang maksimum default adalah 80 karakter.

/// Table Description
table Sales

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

Deklarasi parsial

TMDL tidak memaksa deklarasi objek dalam dokumen yang sama. Namun, ini mirip dengan kelas parsial C# di mana dimungkinkan membagi definisi objek antara beberapa file. Misalnya, Anda dapat mendeklarasikan definisi tabel dalam file [table].tmdl lalu memiliki semua pengukuran dari semua tabel yang ditentukan dalam satu file [measures].tmdl, seperti yang ditunjukkan di sini:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Untuk menghindari kesalahan penguraian, properti yang sama tidak dapat dideklarasikan dua kali. Misalnya, mendeklarasikan dua pengukuran dengan nama yang sama untuk tabel yang sama dalam dua dokumen TMDL yang berbeda menghasilkan kesalahan.

Referensi objek

Anda dapat mereferensikan objek TMDL lain menggunakan kata kunci ref diikuti dengan jenis dan nama objek.

Misalnya, jika Anda membuat serialisasi objek Kolom menggunakan API serialisasi string, hasilnya adalah:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Pengurutan koleksi deterministik

Kata kunci ref juga digunakan untuk menentukan dan mempertahankan urutan koleksi pada pulang-pergi TOM <> TMDL. Sangat penting untuk menghindari diff kontrol sumber pada objek TMDL yang diserialisasikan ke dalam file individual: Tabel, Peran, Budaya, dan Perspektif. Kata kunci ref digunakan pada file TMDL objek induk untuk mendeklarasikan pesanan item dari 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'

Aturan berikut diterapkan:

  • Selama Deserialisasi TMDL:
    • Objek yang dirujuk dalam TMDL tetapi dengan file TMDL yang hilang, diabaikan.
    • Objek tidak direferensikan tetapi dengan file TMDL yang ada, ditambahkan ke akhir koleksi.
  • Selama Serialisasi TMDL:
    • Semua objek koleksi di TOM direferensikan menggunakan kata kunci ref .
    • Koleksi hanya dengan satu item tidak memancarkan ref.
    • Baris kosong tidak dipancarkan di antara ref jika jenis objek yang sama.

Pemisah nilai properti

Hanya ada dua pemisah/simbol untuk menetapkan nilai properti:

  • Sama dengan (=)

  • Titik dua (:)

    • Digunakan untuk setiap nilai properti non-ekspresi. Termasuk properti yang menyimpan referensi model.

Indentasi

TMDL menggunakan aturan indentasi spasi putih yang ketat untuk menunjukkan struktur hierarki TOM. Dokumen TMDL menggunakan aturan indentasi tab tunggal default.

Setiap objek dapat memiliki tiga tingkat indentasi:

  • Tingkat 1 - Deklarasi Objek
    • Tingkat 2 - Properti Objek
      • Tingkat 3 - Ekspresi multibaris properti objek

Dalam dokumen TMDL, indentasi diterapkan dalam kasus berikut:

  • Antara header bagian objek dan properti objek (tabel -> properti).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Antara objek dan objek turunannya (tabel -> pengukuran).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Antara objek dan ekspresi multibarisnya (tabel -> pengukuran -> ekspresi).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Ekspresi multibaris harus diindentasi satu tingkat lebih dalam dari properti objek dan seluruh ekspresi harus berada di dalam tingkat indentasi tersebut (lihat ekspresi).

Database dan objek anak langsung Model tidak perlu diindentasi karena secara implisit diasumsikan berlapis di bawah Model akar atau Database:

  • model
  • tabel
  • ekspresi bersama
  • peran
  • budaya
  • Perspektif
  • hubungan
  • sumber data
  • grup kueri
  • anotasi tingkat model
  • properti yang diperluas tingkat model

Tidak mengikuti aturan indentasi ini menghasilkan kesalahan penguraian.

Whitespace

TMDL secara default menerapkan aturan berikut ke spasi kosong dalam nilai properti dan ekspresi, ketika tidak diapit dalam backtick (```) atau tanda kutip ganda ("):

  • Pada nilai properti, spasi di depan dan di belakang dipangkas.
  • Pada ekspresi, garis spasi kosong di akhir ekspresi dihilangkan.
  • Garis spasi kosong dipangkas menjadi baris kosong (tanpa spasi/tab).

Kapitalisasi

Secara default TMDL API pada serialize/write use camelCase, diterapkan ke:

  • Jenis objek
  • Kata Kunci
  • Nilai enum

Pada deserialisasi/baca, TMDL API tidak peka huruf besar/kecil.

Pertimbangan dan batasan

Sekarang setelah Anda memiliki pemahaman tentang TMDL, pastikan untuk melihat Mulai menggunakan TMDL untuk mempelajari cara mendapatkan dan menyebarkan representasi model TMDL dari model semantik Power BI.