Язык определения табличной модели (TMDL)

Применимо к: SQL Server 2016 и более поздних версий Analysis Services Azure Analysis Services Fabric/Power BI Premium

Важно!

Язык определения табличной модели (TMDL) в настоящее время находится на этапе предварительной версии. Функциональные возможности и документация в предварительной версии с высокой вероятностью могут изменяться.

Язык определения табличных моделей (TMDL) — это синтаксис определения объектной модели для табличных моделей данных на уровне совместимости 1200 или выше.

Ключевые элементы TMDL:

  • Полная совместимость со всей табличной объектной моделью (TOM). Каждый объект TMDL предоставляет те же свойства, что и TOM.
  • Текстовый и оптимизированный для взаимодействия с человеком и удобочитаемости. TMDL использует грамматический синтаксис, аналогичный YAML. Каждый объект TMDL представлен в тексте с минимальными разделителями и использует отступы для демаркации отношений "родители-потомки".
  • Улучшенные возможности редактирования, особенно для свойств с внедренными выражениями из различных типов контента, таких как выражение анализа данных (DAX) и M.
  • Лучше всего подходит для совместной работы благодаря представлению папки, где каждый объект модели имеет отдельное представление файла, что делает его более удобным для системы управления версиями.

Важным аспектом TMDL является использование отступов пробелов для обозначения структуры объекта TOM. В следующем примере показано, насколько легко представить табличную модель при использовании 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

В отличие от TMSL, TMDL использует структуру папок. Структура папок по умолчанию имеет только один уровень вложенных папок, все с TMDL-файлами внутри:

  • cultures
  • перспективы
  • Роли
  • В таблицах

И корневые файлы для:

  • База данных
  • model
  • relationships
  • выражения
  • datasources

Ниже приведен пример папки TMDL:

Папка с TMDL-представлением модели

К определениям относятся:

  • Один файл для определения базы данных.
  • Один файл для определения модели.
  • Один файл для всех источников данных в модели.
  • Один файл для всех выражений в модели.
  • Один файл для всех связей в модели.
  • Один файл для каждой лингвистической схемы языка и региональных параметров.
  • По одному файлу для каждой перспективы.
  • По одному файлу для каждой роли.
  • По одному файлу для каждой таблицы.
  • Все внутренние свойства метаданных таблиц (столбцы, иерархии, секции,...) находятся в файле TMDL родительской таблицы.

TMDL API

Аналогично языку TMSL, существует класс для обработки сериализации TMDL. Для TMDL класс — TmdlSerializer в пространстве имен Microsoft.AnalysisServices.Tabular .

Класс TmdlSerializer предоставляет методы для сериализации и десериализации документов TMDL:

Сериализация папок

public static void SerializeDatabaseToFolder (Database database, string path)

  • Получает объект базы данных TOM и выходной путь TMDL.
  • Сериализует базу данных TOM в представление папки TMDL.

Дополнительные сведения о сериализации в папку.

public static Database DeserializeDatabaseFromFolder (string path)

  • Получает полный путь к папке TMDL.
  • Возвращает представление объекта базы данных TOM папки TMDL.

Дополнительные сведения о десериализации из папок.

Сериализация строк

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

  • Получает объект TOM и возвращает его текстовое представление TMDL.

Дополнительные сведения о сериализации объекта в строку.

Потоковая сериализация

Вы можете сериализовать и десериализовать TMDL в потоки и из потоков, что позволяет преобразовывать объект TOM в потоки байтов для хранения, передачи и взаимодействия между платформами. Api Stream также позволяет управлять загрузкой документов TMDL и выходными документами TMDL.

Сериализация потока TMDL обрабатывается классом MetadataSerializationContext .

Узнайте больше о сериализации в TMDL и из нее с помощью потоков.

Язык TMDL

Объявление объекта

За исключением объекта Server, TMDL предоставляет все дерево объектов базы данных TOM в пространстве имен Microsoft.AnalysisServices.Tabular.

Объект TMDL объявляется путем указания типа объекта TOM и его имени. В следующем примере кода за каждым типом объекта: model, tablecolumn следует имя объекта.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Такие объекты, как partition или measure , имеют свойства по умолчанию , которые могут быть назначены после разделителя равенства (=) в той же строке объявления объекта или в следующей строке для многострочного выражения:

table Sales

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

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

Имя объекта TMDL должно быть заключено в одинарные кавычки ('), если оно содержит любой из следующих символов:

  • Точка (.)
  • Равно (=)
  • Двоеточие (:)
  • Одна кавычка (')
  • Пробел ( )

Если имя объекта содержит одинарные кавычки ('), используйте две одинарные кавычки, чтобы экранировать его.

Свойства объекта

Свойства объекта указываются после объявления объекта или многострочного выражения свойства объекта по умолчанию. Значения свойств объекта указываются после разделителя двоеточия (:). Пример:

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"

К значениям свойств применяются следующие правила:

  • Значение должно находиться в одной строке после двоеточия и не может содержать несколько строк.

  • Значения свойств Text

    • Начальные и конечные двойные кавычки являются необязательными и автоматически удаляются во время сериализации.
    • Должен быть заключен в двойные кавычки ("), если текст содержит пробелы в начале или в начале.
    • Если значение заключено в двойные кавычки, используйте две двойные кавычки, чтобы экранировать их (см displayFolder . свойство в примере кода выше).
  • Логические свойства можно задать с помощью стандартного синтаксиса пары "ключ-значение", как в 'isAvailableInMdx' предыдущем примере. Их также можно задать с помощью синтаксиса ярлыка, в котором объявляется и true подразумевается только имя свойства. См., например, свойство isHidden в предыдущем примере.

Ссылки на именованные объекты

Некоторые свойства объектов содержат ссылки на другие объекты модели, например:

  • Ссылка на столбец на уровнях иерархии.
  • Ссылка sortByColumn в каждом столбце таблицы.
  • Ссылка на таблицу,столбец/меру в перспективах.

В TMDL ссылки создаются с использованием имени объекта и соответствуют тем же требованиям escape-преобразования и одинарной кавычки ('), включающим требования объявления объекта. В следующем примере кода отображаются свойства объекта, которые содержат ссылку на другой объект: column.sortByColumn, level.columnperspectiveMeasure.measure и perspectiveTable.table.


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

Если необходимо ссылаться на полное имя, TMDL использует точечное нотацию для ссылки на объект, например: 'Table 1'.'Column 1'

Дочерние объекты

Дерево объектов TOM содержит дочерние объекты во многих местах и на разных уровнях. Пример:

  • Объект модели содержит объекты таблицы, роли и выражения.
  • Объект таблицы содержит объекты column, measure и hierarchy.

TMDL не объявляет дочерние коллекции явным образом. Вместо этого все применимые дочерние элементы в область соответствующего родительского элемента неявно составляют элементы соответствующей коллекции. Например, все элементы столбцов в область конкретной таблицы становятся элементами коллекции столбцов этой таблицы в TOM, как показано ниже:

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

Дочерние объекты не обязательно должны быть смежными. Например, можно объявлять столбцы и меры в любом порядке и перемешивание.

Свойства по умолчанию

Некоторые типы объектов имеют свойство по умолчанию, которое в большинстве случаев обрабатывается как выражения. Свойство по умолчанию зависит от типа объекта. Если применимо, значение свойства или выражение указывается после разделителя равенства (=) после объявления раздела.

Поддерживаемый синтаксис:

  • Значение указывается в той же строке, что и заголовок раздела.
  • Значение указывается как многострочное выражение после заголовка раздела.

В следующем примере кода мера Sales Amount и секция Sales-Partition1 являются одной строкой, а мера Quantity — многострочно:

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

Выражения

Существуют свойства объектов, которые, будучи текстовым свойством в TOM, получают специальный анализ в TMDL. Весь текст читается дословно, так как он может содержать специальные символы, такие как кавычки или квадратные скобки в выражениях M или DAX. Выражения могут быть многострочные или однострочные. Если многострочный, они должны находиться в строке сразу после объявления свойства или объекта.

Значение выражения в TMDL указывается после равного разделителя (=), как в следующем примере:

table Table1

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

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

К выражениям применяются следующие специальные правила:

  • Многострочное выражение должно быть отступом на один уровень глубже до свойств родительского объекта, и все выражение должно находиться в пределах этого уровня отступа.
  • Все пробелы внешнего отступа удаляются за пределы уровня отступа родительского объекта.
  • Вертикальные пробелы (пустые строки без пробелов) разрешены и считаются частью выражения.
  • Конечные пустые строки и пробелы удаляются.
  • Чтобы применить другой отступ или сохранить конечные пустые строки или пробелы, используйте три обратных символа (```).
  • По умолчанию сериализатор TMDL заключает в обратные тики, если значение выражения содержит что-либо, что может привести к изменению при круговой реплике (например, конечные пробелы, пустые строки с пробелами).

Выражения, заключенные в три обратных выражения (```), считываются дословно, включая отступы, пустые строки и пробелы. Разделитель должен применяться сразу после знака равенства (=) и строки, следующей за выражением, и после него ничего не должно быть, как в следующем примере:

table Table1

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

            ```

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

Использование трех обратных разделителей (```) является необязательным и требуется только в уникальных ситуациях. В большинстве случаев использование правильных отступов и объявления объекта обеспечивает правильный анализ любого выражения, добавляемого в свойство .

Если выражение заключено в обратные тики, применяются следующие правила:

  • Все, что находится между тремя обратными знаками (```), считается частью многоблочного выражения, и правила отступа TMDL не применяются. Конечный разделитель определяет отступ в выражении.
  • Относительный отступ в выражении сохраняется. Конечный разделитель (```) определяет левую границу выражения (см. "Measure1" в предыдущем примере).

Следующие свойства обрабатываются как выражения:

Тип объекта Свойство Язык выражений
Мера Выражение DAX
MPartitionSource Expression M
CalculatedPartitionSource Выражение DAX
QueryPartitionSource Запрос NativeQuery
CalculationItem Выражение DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
КПЭ StatusExpression, TargetExpression, TrendExpression DAX
LinguisticMetadata Содержимое XML или JSON
JsonExtendedProperty Значение Json
FormatStringDefintion Выражение DAX
DataCoverageDefinition Выражение DAX
CalculationGroupExpression Выражение DAX
NamedExpression Выражение DAX
DetailRowsDefinition Выражение DAX
TablePermission FilterExpression DAX
CalculatedColumn Выражение DAX

Свойства по умолчанию по типу объекта

В следующей таблице показаны язык свойств и выражений по умолчанию по типам объектов:

Тип объекта Свойство по умолчанию Язык выражений
Мера Выражение DAX
CalculatedColumn Выражение DAX
CalculationItem Выражение DAX
FormatStringDefinition Выражение DAX
DetailRowsDefinition Выражение DAX
ВычислениеExpression Выражение DAX
DataCoverageDefinition Выражение DAX
TablePermission FilterExpression DAX
ColumnPermission MetadataPermission Перечисление MetadataPermission
NamedExpression Expression M
MPartitionSource Expression M
CalculatedPartitionSource Выражение DAX
JsonExtendedProperty Значение Json
Annotation Значение Текст
StringExtendedProperty Значение Текст
DataSource Тип Перечисление DataSourceType
Секция Тип источника Перечисление PartitionSourceType
ChangedProperty Свойство Текст свойства
ExternalModelRoleMember MemberType Перечисление RoleMemberType
Любое пользовательское свойство JSON (например, DataAccessOptions) Документ JSON Json
LinguisticMetadata Содержимое Json

Описания

TMDL обеспечивает первоклассную поддержку описаний. В целях документации по модели рекомендуется предоставить описания для каждого объекта TOM. TMDL обрабатывает описания как специальное свойство с явной поддержкой синтаксиса. В соответствии с примерами из многих других языков описания указываются поверх каждого объявления объекта с помощью синтаксиса с тройной косой чертой (///).

Пробелы между концом блока описания и маркером типа объекта не допускаются.

Описания можно разделить на несколько строк. Сериализатор TMDL разбивает описания объектов на несколько строк, чтобы не превышать максимальную длину создаваемых строк документа. Максимальная длина по умолчанию составляет 80 символов.

/// Table Description
table Sales

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

Частичное объявление

TMDL не принудительно объявляет объект в одном документе. Однако это похоже на разделяемые классы C# , где можно разделить определение объекта между несколькими файлами. Например, можно объявить определение таблицы в файле [table].tmdl, а затем все меры из всех таблиц определить в одном файле [measures].tmdl, как показано ниже:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Чтобы избежать ошибки синтаксического анализа, одно и то же свойство нельзя объявить дважды. Например, объявление двух мер с одинаковым именем для одной таблицы в двух разных документах TMDL приводит к ошибке.

Ссылки на объекты

Вы можете ссылаться на другой объект TMDL, используя ссылку ключевое слово за которым следует тип и имя объекта.

Например, если сериализовать объект Column с помощью API сериализации строк, результат будет следующим:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Детерминированное упорядочение коллекций

Ссылка ключевое слово также используется для определения и сохранения порядка коллекций для циклов TOM <> TMDL. Особенно важно избегать diff системы управления версиями в объектах TMDL, которые сериализуются в отдельные файлы: таблицы, роли, язык и региональные параметры и перспективы. Ссылка ключевое слово используется в файле TMDL родительского объекта для объявления порядка элементов из 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'

Применяются следующие правила:

  • Во время десериализации TMDL:
    • Объекты, на которые ссылается TMDL, но с отсутствующим файлом TMDL, игнорируются.
    • Объекты, на которые не ссылается, но с существующим файлом TMDL, добавляются в конец коллекции.
  • Во время сериализации TMDL:
    • Все объекты коллекции в TOM ссылаются с помощью ссылки ключевое слово.
    • Коллекции, имеющие только один элемент, не выдают ссылку.
    • Пустые строки не создаются между ссылок, если объект одного типа.

Разделители значений свойств

Существует только два разделителя или символа для назначения значения свойства:

Indentation;

TMDL использует строгие правила отступов пробелов для обозначения структуры иерархии TOM. В документе TMDL используется правило отступа с одной вкладкой по умолчанию.

Каждый объект может иметь три уровня отступа:

  • Уровень 1 . Объявление объекта
    • Уровень 2. Свойства объекта
      • Уровень 3. Многострочное выражение свойства объекта

В документе TMDL отступ применяется в следующих случаях:

  • Между заголовком раздела объекта и свойствами объекта (таблица —> свойства).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Между объектом и его дочерними объектами (таблица —> меры).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Между объектом и его многостроковых выражений (таблица —> мера —> выражение).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Многострочный отступ выражений должен быть на один уровень глубже, чем свойства объекта, и все выражение должно находиться в пределах этого уровня отступа (см. выражения).

База данных и прямые дочерние объекты Model не требуют отступа, так как они неявно считаются вложенными в корневую модель или базу данных:

  • model
  • В таблицах
  • общие выражения
  • Роли
  • cultures
  • перспективы
  • relationships
  • источники данных
  • группы запросов
  • Заметки на уровне модели
  • Расширенные свойства на уровне модели

Если не следовать этим правилам отступа, возникает ошибка синтаксического анализа.

Пробелы

TMDL по умолчанию применяет следующие правила к пробелам в значениях свойств и выражений, если они не заключены в обратные знаки (```) или двойные кавычки ("):

  • В значениях свойств усекаются начальные и конечные пробелы.
  • В выражениях строки пробелов в конце выражений удаляются.
  • Строки пробелов обрезаются до пустых строк (без пробелов или табуляции).

Регистр

По умолчанию API TMDL при сериализации и записи использует camelCase, применяемый к:

  • Типы Object
  • Keywords
  • Значения перечисления

При десериализации и чтении API TMDL не учитывает регистр.

Рекомендации и ограничения

Теперь, когда у вас есть представление о TMDL, ознакомьтесь со статьей Начало работы с TMDL , чтобы узнать, как получить и развернуть представление модели TMDL семантической модели Power BI.