Compartir a través de


Lenguaje de definición de modelos tabulares (TMDL)

Se aplica a: SQL Server 2016 y versiones posteriores Analysis Services Azure Analysis Services Fabric/Power BI Premium

El lenguaje de definición de modelos tabulares (TMDL) es una sintaxis de definición del modelo de objetos para los modelos de datos tabulares en el nivel de compatibilidad 1200 o superior.

Entre los elementos clave de TMDL se incluyen:

  • Compatibilidad completa con todo el modelo de objetos tabulares (TOM). Cada objeto TMDL expone las mismas propiedades que TOM.
  • Basado en texto y optimizado para la interacción y legibilidad humanas. TMDL usa una sintaxis gramatical similar a YAML. Cada objeto TMDL se representa en texto con delimitadores mínimos y usa sangría para marcar las relaciones de elementos primarios y secundarios.
  • Mejor experiencia de edición, especialmente en las propiedades con expresiones insertadas de diferentes tipos de contenido, como La expresión de análisis de datos (DAX) y M.
  • Mejor para la colaboración debido a su representación de carpeta en la que cada objeto de modelo tiene una representación de archivo individual, lo que facilita el control de código fuente.

Un aspecto importante de TMDL es el uso de sangría de espacios en blanco para indicar una estructura de objetos TOM. En el ejemplo siguiente se muestra lo fácil que es representar un modelo tabular al usar 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]

Estructura de carpetas TMDL

A diferencia de TMSL, TMDL usa una estructura de carpetas. La estructura de carpetas predeterminada solo tiene un nivel de subcarpetas, todo ello con archivos .tmdl dentro de:

  • Culturas
  • Perspectivas
  • Papeles
  • Mesas

Y los archivos raíz para:

Este es un ejemplo de una carpeta 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

Las definiciones incluyen:

  • Un archivo para la definición de la base de datos.
  • Un archivo para la definición del modelo.
  • Un archivo para todos los orígenes de datos del modelo.
  • Un archivo para todas las expresiones del modelo.
  • Un archivo para todas las funciones (funciones definidas por el usuario DAX en el modelo).
  • Un archivo para todas las relaciones del modelo.
  • Un archivo para cada esquema lingüístico cultural.
  • Un archivo para cada perspectiva.
  • Un archivo para cada rol.
  • Un archivo para cada tabla.
  • Todas las propiedades de metadatos internas de las tablas (columna, jerarquías, particiones,...) residen en el archivo TMDL de la tabla primaria.

TMDL API

De forma similar al Lenguaje de Scripting de Modelos Tabulares (TMSL), hay una clase para gestionar la serialización de TMDL. Para TMDL, la clase es TmdlSerializer, en el espacio de nombres Microsoft.AnalysisServices.Tabular .

La clase TmdlSerializer expone métodos para serializar y deserializar documentos TMDL:

Serialización de carpetas

public static void SerializeDatabaseToFolder (Database database, string path)

  • Recibe un objeto de base de datos TOM y la ruta de acceso de salida de TMDL.
  • Serializa la base de datos TOM en una representación de carpeta TMDL.

Obtenga más información sobre cómo serializar en una carpeta.

public static Database DeserializeDatabaseFromFolder (string path)

  • Recibe una ruta de acceso completa a una carpeta TMDL.
  • Devuelve la representación del objeto de base de datos TOM de la carpeta TMDL.

Obtenga más información sobre cómo deserializar desde carpetas.

Serialización de cadenas

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

  • Recibe un objeto TOM y devuelve su representación de texto TMDL.

Obtenga más información sobre cómo serializar un objeto en una cadena.

Serialización de secuencias

Puede serializar o deserializar TMDL hacia y desde secuencias, lo que le permite convertir un objeto TOM en flujos de bytes para el almacenamiento, la transmisión y la interoperabilidad entre plataformas. Stream API también permite controlar qué documentos TMDL se cargan y qué documentos TMDL se generan.

La serialización tmDL Stream se controla mediante la clase MetadataSerializationContext .

Obtenga más información sobre cómo serializar a/de TMDL mediante secuencias.

Idioma TMDL

Declaración de objeto

Excepto por el objeto Server, TMDL expone todo el árbol de objetos de la base de datos TOM en el espacio de nombres Microsoft.AnalysisServices.Tabular.

Un objeto TMDL se declara especificando el tipo de objeto TOM seguido de su nombre. En el ejemplo de código siguiente, cada tipo de objeto: model, table, column va seguido de un nombre de objeto.

model Model    
    culture: en-US    

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

    column 'Customer Key'
        datatype: int64
        sourceColumn: CustomerKey

Objetos como partition o measure tienen propiedades predeterminadas que se pueden asignar después del delimitador igual (=) en la misma línea de la declaración de objeto o en la siguiente línea para una expresión de varias líneas:

table Sales

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

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

El nombre del objeto TMDL debe incluirse entre comillas simples (') si incluye cualquiera de los caracteres siguientes:

  • Punto (.)
  • Igual a (=)
  • Dos puntos (:)
  • Comilla simple (')
  • Espacio en blanco ( )

Si un nombre de objeto contiene comillas simples ('), use dos comillas simples para escaparlas.

Propiedades del objeto

Las propiedades del objeto se especifican después de la declaración de objeto o la expresión de varias líneas de la propiedad predeterminada del objeto. Los valores de las propiedades del objeto se especifican siguiendo el delimitador de dos puntos (:). Por ejemplo:

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"

Las reglas siguientes se aplican a los valores de propiedad:

  • El valor debe estar en la misma línea que sigue a los dos puntos y no puede tener varias líneas.

  • Valores de propiedad text

    • Las comillas dobles iniciales y finales son opcionales y se quitan automáticamente durante la serialización.
    • Debe incluirse entre comillas dobles (") si el texto contiene espacios en blanco finales o iniciales.
    • Cuando se incluye entre comillas dobles, si el valor contiene comillas dobles, use dos comillas dobles para escaparlas (vea la propiedad displayFolder en el ejemplo de código anterior).
  • Las propiedades booleanas se pueden establecer mediante la sintaxis de par clave-valor estándar, como con la 'isAvailableInMdx' propiedad del ejemplo anterior. También se pueden configurar mediante una sintaxis abreviada en la que solo se declara el nombre de la propiedad y true está implícito. Vea, por ejemplo, la propiedad 'isHidden' en el ejemplo anterior.

Referencias de objeto con nombre

Algunas propiedades de objeto contienen referencias a otros objetos de modelo, por ejemplo:

  • Referencia de columna en niveles de jerarquía.
  • referencia sortByColumn en cada columna de tabla.
  • Referencia de tabla,columna/medida en perspectivas.

En TMDL, las referencias se realizan con el nombre del objeto y siguen los mismos requisitos de escape y de uso de comillas simples (') al declarar un objeto. En el ejemplo de código siguiente, verá propiedades de objeto que contienen una referencia a otro objeto: column.sortByColumn, level.columny perspectiveMeasure.measureperspectiveTable.table .


table Product

    column Category
        sortByColumn: 'Category Order'    

 hierarchy 'Product Hierarchy'

  level Category   
   column: Category  
 

perspective Product

 perspectiveTable Product

        perspectiveMeasure '# Products'

Si es necesario hacer referencia a un nombre totalmente calificado, TMDL usa la notación de punto para hacer referencia a un objeto, por ejemplo: 'Table 1'.'Column 1'

Objetos secundarios

El árbol de objetos TOM contiene objetos secundarios en muchos lugares y en distintos niveles. Por ejemplo:

  • Un objeto de modelo contiene objetos de tabla, rol y expresión.
  • Un objeto table contiene objetos de columna, medida y jerarquía.

TMDL no declara colecciones secundarias explícitamente. En su lugar, todos los elementos secundarios aplicables dentro del ámbito de su elemento primario respectivo componen implícitamente los elementos de la colección correspondiente. Por ejemplo, todos los elementos de columna dentro del ámbito de una tabla determinada se convierten en elementos de la colección de columnas de esa tabla en TOM, como se muestra aquí:

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

Los objetos secundarios no tienen que ser contiguos. Por ejemplo, puede declarar columnas y medidas en cualquier orden e intercalación.

Propiedades predeterminadas

Algunos tipos de objeto tienen una propiedad predeterminada que la mayoría de las veces se tratan como expresiones. La propiedad predeterminada es específica del tipo de objeto. Cuando sea aplicable, el valor de propiedad o la expresión se especifica tras el delimitador de igualdad (=), seguido de la declaración de la sección.

Sintaxis admitida:

  • El valor se especifica en la misma línea que el encabezado de sección.
  • El valor se especifica como una expresión de varias líneas siguiendo el encabezado de sección.

En el ejemplo de código siguiente, la medida Sales Amount y la partición Sales-Partition1 son una sola línea y la medida Quantity es de varias líneas:

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

Expresiones

Hay propiedades de objeto que, al ser una propiedad de texto en TOM, obtienen un análisis especial en TMDL. El texto completo se lee textualmente porque puede incluir caracteres especiales como comillas o corchetes en expresiones M o DAX. Las expresiones pueden ser de varias líneas o de una sola línea. Si hay varias líneas, deben encontrarse en la línea inmediatamente después de la declaración de propiedad o objeto.

Se especifica un valor de expresión en TMDL siguiendo un delimitador igual a (=), como en el ejemplo siguiente:

table Table1

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

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

Las siguientes reglas especiales se aplican a las expresiones:

  • Las expresiones de varias líneas deben aplicar sangría a un nivel más profundo a las propiedades del objeto primario y toda la expresión debe estar dentro de ese nivel de sangría.
  • Todos los espacios en blanco de sangría externa se quitan más allá del nivel de sangría del objeto primario.
  • Se permiten espacios en blanco verticales (líneas en blanco sin espacios en blanco) y se consideran parte de la expresión.
  • Se quitan las líneas en blanco finales y los espacios en blanco.
  • Para aplicar una sangría diferente o para conservar líneas en blanco finales o espacios en blanco, use las tres líneas inversas (```) envolventes.
  • De forma predeterminada, el serializador TMDL se incluirá con acentos versos si el valor de expresión contiene algo que podría provocar una modificación en el recorrido de ida y vuelta (por ejemplo, espacios en blanco finales, líneas en blanco con espacios en blanco).

Las expresiones incluidas con tres comillas invertidas (```) se leen textualmente, incluidas la sangría, los saltos de línea y los espacios. El delimitador debe aplicarse inmediatamente después del signo igual (=) y la línea que sigue a la expresión y no puede tener nada después, como en el ejemplo siguiente:

table Table1

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

            ```

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

El uso del delimitador de tres acentos inversas (```) es opcional y solo es necesario en situaciones únicas. En la mayoría de las situaciones, el uso de la sangría correcta y la declaración de objeto garantiza el análisis correcto de cualquier expresión que agregue a la propiedad .

Cuando la expresión se incluye dentro de las operaciones inversas, se aplican las reglas siguientes:

  • Todo lo que hay entre tres acentos inversas (```) se considera parte de la expresión de varios bloques y las reglas de sangría tmDL no se aplican. El delimitador final determina la sangría dentro de la expresión.
  • Se conserva la sangría relativa dentro de la expresión. El delimitador final (```) determina el límite izquierdo de la expresión (vea "Measure1" en el ejemplo anterior).

Las siguientes propiedades se tratan como expresiones:

Tipo de objeto Propiedad Lenguaje de expresión
Medir Expresión DAX
Función Expresión DAX
MPartitionSource Expresión M
CalculatedPartitionSource Expresión DAX
QueryPartitionSource Consulta NativeQuery
CalculationItem Expresión DAX
BasicRefreshPolicy SourceExpression, PollingExpression M
KPI Expresión de Estado, Expresión de Objetivo, Expresión de Tendencia DAX
LinguisticMetadata Contenido XML o Json
JsonExtendedProperty Valor Json
FormatStringDefintion Expresión DAX
DataCoverageDefinition Expresión DAX
CalculationGroupExpression Expresión DAX
NamedExpression Expresión DAX
DetailRowsDefinition Expresión DAX
TablePermission FilterExpression DAX
CalculatedColumn Expresión DAX

Propiedades predeterminadas por tipo de objeto

En la tabla siguiente se muestran la propiedad predeterminada y el lenguaje de expresión por tipo de objeto:

Tipo de objeto Propiedad predeterminada Lenguaje de expresión
Medir Expresión DAX
Función Expresión DAX
CalculatedColumn Expresión DAX
CalculationItem Expresión DAX
FormatStringDefinition Expresión DAX
DetailRowsDefinition Expresión DAX
CalculationExpression Expresión DAX
DataCoverageDefinition Expresión DAX
TablePermission FilterExpression DAX
ColumnPermission MetadataPermission Enumeración PermisoDeMetadatos
NamedExpression Expresión M
MPartitionSource Expresión M
CalculatedPartitionSource Expresión DAX
JsonExtendedProperty Valor Json
Anotación Valor Mensaje de texto
StringExtendedProperty Valor Mensaje de texto
DataSource Tipo Enumeración DataSourceType
Partición SourceType Enumeración PartitionSourceType
ChangedProperty Propiedad Texto de propiedad
ExternalModelRoleMember MemberType Enumeración RoleMemberType
Cualquier propiedad JSON personalizada (por ejemplo, DataAccessOptions) Documento JSON Json
LinguisticMetadata Contenido Json

Descripciones

TMDL proporciona compatibilidad de primera clase con descripciones. Con fines de documentación del modelo, el procedimiento recomendado es proporcionar descripciones para cada objeto TOM. TMDL trata las descripciones como una propiedad especial con compatibilidad explícita con sintaxis. Siguiendo los ejemplos de muchos otros lenguajes, las descripciones se especifican sobre cada declaración de objeto mediante la sintaxis de barra diagonal triple (///).

No se permite ningún espacio en blanco entre el extremo del bloque de descripción y el token de tipo de objeto.

Las descripciones se pueden dividir entre varias líneas. El serializador TMDL divide las descripciones de objetos en varias líneas para mantener las líneas de documento emitidas bajo la longitud máxima. La longitud máxima predeterminada es de 80 caracteres.

/// Table Description
table Sales

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

Declaración parcial

TMDL no fuerza la declaración de objeto en el mismo documento. Sin embargo, es similar a las clases parciales de C# donde es posible dividir la definición de objeto entre varios archivos. Por ejemplo, puede declarar una definición de tabla en un archivo [table].tmdl y, a continuación, tener todas las medidas de todas las tablas definidas en un único archivo [measures].tmdl, como se muestra aquí:

table Sales

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

table Product

    measure CountOfProduct = COUNTROWS(…)

Para evitar un error de análisis, la misma propiedad no se puede declarar dos veces. Por ejemplo, declarar dos medidas con el mismo nombre para la misma tabla en dos documentos TMDL diferentes produce un error.

Referencias de objeto

Puede hacer referencia a otro objeto TMDL mediante la palabra clave ref seguida del tipo de objeto y el nombre.

Por ejemplo, si serializa un objeto Column mediante la API de serialización de cadenas, el resultado será:

ref table Table1
	column Column1
		datatype: int64
		sourceColumn: Column1

Ordenación de colección determinista

La palabra clave ref también se usa para definir y conservar el orden de recopilación en los recorridos de ida y vuelta de TOM <> TMDL. Es especialmente importante evitar diferencias de control de código fuente en objetos TMDL que se serializan en archivos individuales: tablas, roles, referencias culturales y perspectivas. La palabra clave ref se usa en el archivo TMDL del objeto primario para declarar la ordenación de elementos desde 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'

Se aplican las reglas siguientes:

  • Durante la deserialización de TMDL:
    • Los objetos a los que se hace referencia en TMDL pero que faltan en el archivo TMDL se omiten.
    • Los objetos no a los que se hace referencia, pero con el archivo TMDL existente, se anexan al final de la colección.
  • Durante la serialización de TMDL:
    • Se hace referencia a todos los objetos de colección de TOM mediante la palabra clave ref .
    • Las colecciones con un solo elemento no emiten una referencia.
    • Las líneas en blanco no se emiten entre las referencias si el mismo tipo de objeto.

Delimitadores de valor de propiedad

Solo hay dos delimitadores o símbolos para asignar un valor de propiedad:

  • Igual a (=)

  • Dos puntos (:)

    • Se usa para cada valor de propiedad que no es de expresión. Incluir propiedades que contienen referencias de modelo.

Sangría

TMDL usa reglas estrictas de sangría de espacios en blanco para indicar la estructura de la jerarquía de TOM. Un documento TMDL usa una regla de sangría de tabulación única predeterminada.

Cada objeto puede tener tres niveles de sangría:

  • Nivel 1: Declaración de objeto
    • Nivel 2: Propiedades del objeto
      • Nivel 3: expresiones de varias líneas de propiedad de objeto

Dentro de un documento TMDL, la sangría se aplica en los casos siguientes:

  • Entre un encabezado de sección de objeto y las propiedades del objeto (tabla de propiedades ->).

    table Sales
        isHidden
        lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
    
  • Entre un objeto y sus objetos secundarios (tabla -> medidas).

    table Sales
    
        measure 'Sales Amount' = SUMX(...)
    
        measure 'Total Quantity' = SUM(...)
    
  • Entre un objeto y sus expresiones multilineales (tabla -> medida -> expresión).

    table Sales
    
        measure 'Sales Amount' = 
                var result = SUMX(...)
                return result
            formatString: $ #,##0
    
  • Las expresiones de varias líneas deben aplicar sangría a un nivel más profundo que las propiedades del objeto y toda la expresión debe estar dentro de ese nivel de sangría (vea expresiones).

No es necesario aplicar sangría a la base de datos ni a los objetos secundarios directos del modelo porque se asumen implícitamente anidados en el modelo raíz o la base de datos:

  • modelo
  • Mesas
  • expresiones compartidas
  • Papeles
  • Culturas
  • Perspectivas
  • Relaciones
  • orígenes de datos
  • grupos de consultas
  • anotaciones de nivel de modelo
  • propiedades extendidas de nivel de modelo

No seguir estas reglas de sangría genera un error de análisis.

Espacios

TMDL aplica por defecto las siguientes reglas a los espacios en blanco dentro de los valores de propiedad y expresión, cuando no se incluyen entre acentos graves (```) o comillas dobles ("):

  • En los valores de propiedad, se recortan los espacios en blanco iniciales y finales.
  • En las expresiones, se quitan las líneas de espacio en blanco al final de las expresiones.
  • Las líneas de espacios en blanco se recortan a líneas vacías (sin espacios o pestañas).

Cubierta

De forma predeterminada, la API tmDL en serialize/write usa camelCase, aplicada a:

  • Tipos de objeto
  • Palabras clave
  • Valores de enumeración

Al deserializar/leer, la API tmDL no distingue mayúsculas de minúsculas.

Ahora que conoce TMDL, asegúrese de ver Introducción a TMDL para obtener información sobre cómo obtener e implementar una representación de modelo TMDL de un modelo semántico de Power BI.