Langage TMDL (Tabular Model Definition Language)
S’applique à : SQL Server 2016 et versions ultérieures Analysis Services Azure Analysis Services Fabric/Power BI Premium
Important
Le langage TMDL (Tabular Model Definition Language) est actuellement en préversion. Pendant la période de préversion, les fonctionnalités et la documentation sont susceptibles de changer.
Le langage TMDL (Tabular Model Definition Language) est une syntaxe de définition de modèle objet pour les modèles de données tabulaires au niveau de compatibilité 1200 ou supérieur.
Les éléments clés de TMDL sont les suivants :
- Compatibilité totale avec l’ensemble du modèle d’objet tabulaire (TOM). Chaque objet TMDL expose les mêmes propriétés que TOM.
- Basé sur du texte et optimisé pour l’interaction humaine et la lisibilité. TMDL utilise une syntaxe grammaticale similaire à YAML. Chaque objet TMDL est représenté dans du texte avec des délimiteurs minimaux et utilise la mise en retrait pour délimiter les relations parent-enfant.
- Meilleure expérience d’édition, en particulier sur les propriétés avec des expressions incorporées de différents types de contenu, comme DAX (Data Analysis Expression) et M.
- Mieux pour la collaboration en raison de sa représentation de dossier où chaque objet de modèle a une représentation de fichier individuelle, ce qui le rend plus convivial pour le contrôle de code source.
Un aspect important de TMDL est l’utilisation de la mise en retrait d’espace blanc pour désigner une structure d’objet TOM. L’exemple suivant montre à quel point il est facile de représenter un modèle tabulaire lors de l’utilisation de 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]
Structure des dossiers TMDL
Contrairement à TMSL, TMDL utilise une structure de dossiers. La structure de dossiers par défaut n’a qu’un seul niveau de sous-dossiers, tous avec des fichiers .tmdl à l’intérieur :
- cultures
- perspectives
- roles
- dans des tables
Et les fichiers racines pour :
- database
- model
- relationships
- expressions
- datasources
Voici un exemple de dossier TMDL :
Les définitions sont les suivantes :
- Un fichier pour la définition de base de données.
- Un fichier pour la définition de modèle.
- Un fichier pour toutes les sources de données dans le modèle.
- Un fichier pour toutes les expressions du modèle.
- Un fichier pour toutes les relations dans le modèle.
- Un fichier pour chaque schéma linguistique de culture.
- Un fichier pour chaque perspective.
- Un fichier pour chaque rôle.
- Un fichier pour chaque table.
- Toutes les propriétés de métadonnées internes des tables (Column, Hierarchies, Partitions,...) se trouvent dans le fichier TMDL de la table parente.
TMDL API
À l’instar du langage TMSL (Tabular Model Scripting Language), il existe une classe pour gérer la sérialisation TMDL. Pour TMDL, la classe est TmdlSerializer, sous l’espace de noms Microsoft.AnalysisServices.Tabular .
La classe TmdlSerializer expose des méthodes pour sérialiser et désérialiser des documents TMDL :
Sérialisation des dossiers
public static void SerializeDatabaseToFolder (Database database, string path)
- Reçoit un objet de base de données TOM et le chemin de sortie TMDL.
- Sérialise la base de données TOM dans une représentation de dossier TMDL.
En savoir plus sur la sérialisation dans un dossier.
public static Database DeserializeDatabaseFromFolder (string path)
- Reçoit un chemin d’accès complet à un dossier TMDL.
- Retourne la représentation d’objet de base de données TOM du dossier TMDL.
En savoir plus sur la désérialisation à partir de dossiers.
Sérialisation de chaînes
public static string SerializeObject (MetadataObject object, bool qualifyObject = true)
- Reçoit un objet TOM et retourne sa représentation textuelle TMDL.
En savoir plus sur la sérialisation d’un objet en chaîne.
Sérialisation de flux
Vous pouvez sérialiser/désérialiser TMDL vers/depuis des flux, ce qui vous permet de convertir un objet TOM en flux d’octets pour le stockage, la transmission et l’interopérabilité entre les plateformes. L’API Stream vous permet également de contrôler quels documents TMDL sont chargés et quels documents TMDL sont générés.
La sérialisation du flux TMDL est gérée par la classe MetadataSerializationContext .
En savoir plus sur la sérialisation vers/depuis TMDL à l’aide de flux.
Langage TMDL
Déclaration d’objet
À l’exception de l’objet Server, TMDL expose l’arborescence d’objets TOM Database entière dans l’espace de noms Microsoft.AnalysisServices.Tabular.
Un objet TMDL est déclaré en spécifiant le type d’objet TOM suivi de son nom. Dans l’exemple de code suivant, chaque type d’objet : model
, table
est column
suivi d’un nom d’objet.
model Model
culture: en-US
table Sales
measure Sales = SUM(…)
formatString: $ #,##0
column 'Customer Key'
datatype: int64
sourceColumn: CustomerKey
Les objets comme partition
ou measure
ont des propriétés par défaut qui peuvent être affectées après le délimiteur égal à (=) dans la même ligne de la déclaration d’objet ou dans la ligne suivante pour une expression multiligne :
table Sales
partition Sales-Part1 = m
mode: import
...
measure Sales = SUM(…)
formatString: $ #,##0
measure 'Sales (ly)' =
var ly = ...
return ly
formatString: $ #,##0
Le nom de l’objet TMDL doit être placé entre guillemets simples (') s’il comprend l’un des caractères suivants :
- Point (.)
- Est égal à (=)
- Deux-points ( :)
- Citation simple (')
- Espace blanc ( )
Si un nom d’objet contient des guillemets simples ('), utilisez deux guillemets simples pour le placer dans une séquence d’échappement.
Propriétés des objets
Les propriétés de l’objet sont spécifiées après la déclaration d’objet ou l’expression de propriété par défaut de l’objet. Les valeurs de propriété d’objet sont spécifiées en suivant le délimiteur deux-points ( :). Par exemple :
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"
Les règles suivantes s’appliquent aux valeurs de propriété :
La valeur doit se trouver dans la même ligne qui suit les deux-points et ne peut pas avoir plusieurs lignes.
Valeurs des propriétés text
- Les guillemets doubles de début et de fin sont facultatifs et automatiquement supprimés pendant la sérialisation.
- Doit être placé entre guillemets doubles (« ) si le texte contient un espace blanc de fin ou de début.
- Lorsqu’elle est placée entre guillemets doubles, si la valeur contient des guillemets doubles, utilisez deux guillemets doubles pour les placer dans une séquence d’échappement (voir
displayFolder
la propriété dans l’exemple de code ci-dessus).
Les propriétés booléennes peuvent être définies à l’aide de la syntaxe de paire clé/valeur standard, comme avec la
'isAvailableInMdx'
propriété dans l’exemple précédent. Ils peuvent également être définis à l’aide d’une syntaxe de raccourci où seul le nom de propriété est déclaré ettrue
implicite. Consultez, par exemple, la propriété « isHidden » dans l’exemple précédent.
Références d’objets nommés
Certaines propriétés d’objet contiennent des références à d’autres objets de modèle, par exemple :
- Référence de colonne dans les niveaux hiérarchiques.
- référence sortByColumn dans chaque colonne de table.
- Référence de table/colonne/mesure dans les perspectives.
Dans TMDL, les références sont effectuées à l’aide du nom de l’objet et suivent les mêmes exigences d’échappement et de guillemet unique (') de déclaration d’objet. Dans l’exemple de code suivant, vous voyez des propriétés d’objet qui contiennent une référence à un autre objet : column.sortByColumn
, level.column
et perspectiveMeasure.measure
perspectiveTable.table
.
table Product
column Category
sortByColumn: 'Category Order'
hierarchy 'Product Hierarchy'
level Category
column: Category
perspective Product
perspectiveTable Product
perspectiveMeasure '# Products'
Si nécessaire pour référencer un nom complet, TMDL utilise la notation par points pour référencer un objet, par exemple : 'Table 1'.'Column 1'
Objets enfants
L’arborescence d’objets TOM contient des objets enfants à de nombreux endroits et à différents niveaux. Par exemple :
- Un objet de modèle contient des objets de table, de rôle et d’expression.
- Un objet table contient des objets de colonne, de mesure et de hiérarchie.
TMDL ne déclare pas explicitement les collections enfants. Au lieu de cela, tous les éléments enfants applicables dans l’étendue de leur parent respectif composent implicitement les éléments de la collection correspondante. Par exemple, tous les éléments de colonne dans l’étendue d’une table particulière deviennent des éléments de la collection columns de cette table dans TOM, comme illustré ici :
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])
Les objets enfants n’ont pas besoin d’être contigus. Par exemple, vous pouvez déclarer des colonnes et des mesures dans n’importe quel ordre et entremêlées.
Propriétés par défaut
Certains types d’objets ont une propriété par défaut qui est la plupart du temps traitée comme des expressions. La propriété par défaut est spécifique au type d’objet. Le cas échéant, la valeur ou l’expression de propriété est spécifiée à la suite du délimiteur égal à (=) après la déclaration de section.
Syntaxe prise en charge :
- La valeur est spécifiée sur la même ligne que l’en-tête de section.
- La valeur est spécifiée en tant qu’expression multiligne après l’en-tête de section.
Dans l’exemple de code suivant, la mesure Sales Amount
et la partition Sales-Partition1
sont une seule ligne et la mesure Quantity
est multiligne :
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
Il existe des propriétés d’objet qui, tout en étant une propriété de texte dans TOM, obtiennent une analyse spéciale dans TMDL. L’intégralité du texte est lue textuellement, car elle peut inclure des caractères spéciaux tels que des guillemets ou des crochets dans les expressions M ou DAX. Les expressions peuvent être multilignes ou monolignes. S’ils sont multilignes, ils doivent se trouver dans la ligne immédiatement après la déclaration de propriété ou d’objet.
Une valeur d’expression dans TMDL est spécifiée à la suite d’un délimiteur égal à (=), comme dans l’exemple suivant :
table Table1
partition 'partition 1' = m
mode: import
source =
let
...
in
finalStep
measure Measure1 = SUM(...)
measure Measure2 =
var result = SUMX (
...
)
return result
formatString: $ #,##0
Les règles spéciales suivantes s’appliquent aux expressions :
- Les expressions multilignes doivent être mises en retrait d’un niveau plus profond dans les propriétés de l’objet parent, et l’expression entière doit se trouver dans ce niveau de retrait.
- Tous les espaces blancs de retrait externe sont supprimés au-delà du niveau de retrait de l’objet parent.
- Les espaces blancs verticaux (lignes vides sans espaces blancs) sont autorisés et sont considérés comme faisant partie de l’expression.
- Les lignes vides et les espaces blancs de fin sont supprimés.
- Pour appliquer une mise en retrait différente ou pour conserver les lignes vides ou les espaces blancs de fin, utilisez les trois accents (```) englobants.
- Par défaut, le sérialiseur TMDL contient des accents inverses si la valeur de l’expression contient quelque chose qui pourrait entraîner une modification lors d’un aller-retour (par exemple, des espaces blancs de fin, des lignes vides avec des espaces blancs).
Les expressions entourées de trois accents (```) sont lues textuellement, notamment la mise en retrait, les lignes vides et les espaces blancs. Le délimiteur doit être appliqué immédiatement après le signe égal (=) et la ligne qui suit l’expression et ne peut avoir rien après, comme dans l’exemple suivant :
table Table1
partition partition1 = m
mode: import
source = ```
let
...
in
finalStep
```
measure Measure1 = ```
var myVar = Today()
…
return result
```
L’utilisation du délimiteur à trois backticks (```) est facultative et nécessaire uniquement dans des situations uniques. Dans la plupart des cas, l’utilisation d’une mise en retrait et d’une déclaration d’objet correctes garantit une analyse correcte de l’expression que vous ajoutez à la propriété.
Lorsque l’expression est placée dans des backticks, les règles suivantes s’appliquent :
- Tout ce qui se trouve entre trois backticks (```) est considéré comme faisant partie de l’expression multibloc et les règles de retrait TMDL ne sont pas appliquées. Le délimiteur de fin détermine la mise en retrait dans l’expression.
- La mise en retrait relative dans l’expression est conservée. Le délimiteur de fin (```) détermine la limite de gauche de l’expression (voir « Measure1 » dans l’exemple précédent).
Les propriétés suivantes sont traitées comme des expressions :
Type d'objet | Propriété | Langage d’expression |
---|---|---|
Mesure | Expression | DAX |
MPartitionSource | Expression | M |
CalculatedPartitionSource | Expression | DAX |
QueryPartitionSource | Requête | NativeQuery |
CalculationItem | Expression | DAX |
BasicRefreshPolicy | SourceExpression, PollingExpression | M |
KPI | StatusExpression, TargetExpression, TrendExpression | DAX |
LinguisticMetadata | Contenu | XML ou Json |
JsonExtendedProperty | Valeur | Json |
FormatStringDefintion | Expression | DAX |
DataCoverageDefinition | Expression | DAX |
CalculationGroupExpression | Expression | DAX |
NamedExpression | Expression | DAX |
DetailRowsDefinition | Expression | DAX |
TablePermission | FilterExpression | DAX |
CalculatedColumn | Expression | DAX |
Propriétés par défaut par type d’objet
Le tableau suivant présente la propriété par défaut et le langage d’expression par type d’objet :
Type d’objet | Propriété par défaut | Langage d’expression |
---|---|---|
Mesure | Expression | DAX |
CalculatedColumn | Expression | DAX |
CalculationItem | Expression | DAX |
FormatStringDefinition | Expression | DAX |
DetailRowsDefinition | Expression | DAX |
CalculationExpression | Expression | DAX |
DataCoverageDefinition | Expression | DAX |
TablePermission | FilterExpression | DAX |
ColumnPermission | MetadataPermission | MetadataPermission, énumération |
NamedExpression | Expression | M |
MPartitionSource | Expression | M |
CalculatedPartitionSource | Expression | DAX |
JsonExtendedProperty | Valeur | Json |
Annotation | Valeur | Texte |
StringExtendedProperty | Valeur | Texte |
DataSource | Type | DataSourceType, énumération |
Partition | SourceType | PartitionSourceType, énumération |
ChangedProperty | Propriété | Texte de la propriété |
ExternalModelRoleMember | MemberType | Énumération RoleMemberType |
Toute propriété JSON personnalisée (par exemple, DataAccessOptions) | Document JSON | Json |
LinguisticMetadata | Contenu | Json |
Descriptions
TMDL fournit une prise en charge de première classe pour les descriptions. À des fins de documentation de modèle, la meilleure pratique consiste à fournir des descriptions pour chaque objet TOM. TMDL traite les descriptions comme une propriété spéciale avec une prise en charge syntaxique explicite. À la suite des exemples de nombreux autres langages, les descriptions sont spécifiées par-dessus chaque déclaration d’objet à l’aide de la syntaxe à barres obliques triples (///).
Aucun espace blanc n’est autorisé entre la fin du bloc de description et le jeton de type d’objet.
Les descriptions peuvent être réparties sur plusieurs lignes. Le sérialiseur TMDL divise les descriptions d’objets en plusieurs lignes pour conserver les lignes de document émises sous la longueur maximale. La longueur maximale par défaut est de 80 caractères.
/// Table Description
table Sales
/// This is the Measure Description
/// One more line
measure 'Sales Amount'' = SUM(...)
formatString: #,##0
Déclaration partielle
TMDL ne force pas la déclaration d’objet dans le même document. Toutefois, il est similaire aux classes partielles C# où il est possible de fractionner la définition d’objet entre plusieurs fichiers. Par exemple, vous pouvez déclarer une définition de table dans un fichier [table].tmdl, puis avoir toutes les mesures de toutes les tables définies dans un seul fichier [measures].tmdl, comme illustré ici :
table Sales
measure 'Sales Amount' = SUM(…)
formatString: $ #,##0
table Product
measure CountOfProduct = COUNTROWS(…)
Pour éviter une erreur d’analyse, la même propriété ne peut pas être déclarée deux fois. Par exemple, la déclaration de deux mesures portant le même nom pour la même table dans deux documents TMDL différents génère une erreur.
Références d'objets
Vous pouvez référencer un autre objet TMDL à l’aide de la référence mot clé suivie du type et du nom de l’objet.
Par exemple, si vous sérialisez un objet Column à l’aide de l’API de sérialisation de chaîne, le résultat sera :
ref table Table1
column Column1
datatype: int64
sourceColumn: Column1
Classement déterministe des collections
La référence mot clé est également utilisée pour définir et conserver l’ordre de collecte sur les allers-retours TOM <> TMDL. Il est particulièrement important d’éviter les diff de contrôle de code source sur les objets TMDL qui sont sérialisés dans des fichiers individuels : tables, rôles, cultures et perspectives. Le mot clé ref est utilisé sur le fichier TMDL de l’objet parent pour déclarer le classement d’élément à partir de 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'
Les règles suivantes sont appliquées :
- Pendant la désérialisation TMDL :
- Les objets référencés dans TMDL, mais avec le fichier TMDL manquant, sont ignorés.
- Les objets non référencés, mais avec un fichier TMDL existant, sont ajoutés à la fin de la collection.
- Pendant la sérialisation TMDL :
- Tous les objets de collection dans TOM sont référencés à l’aide de la référence mot clé.
- Les collections avec un seul élément n’émettent pas de référence.
- Les lignes vides ne sont pas émises entre les ref si le même type d’objet.
Délimiteurs de valeur de propriété
Il n’existe que deux délimiteurs/symboles pour affecter une valeur de propriété :
Est égal à (=)
- Utilisé lors de la déclaration d’objet avec la propriété par défaut (ligne multiple et unique)
- Utilisé à chaque propriété d’expression, par exemple partition.expression
Deux-points ( :)
- Utilisé pour chaque valeur de propriété non expression. Y compris les propriétés qui contiennent des références de modèle.
Indentation
TMDL utilise des règles de retrait d’espace blanc strictes pour délimiter la structure de la hiérarchie TOM. Un document TMDL utilise une règle de retrait par onglet unique par défaut.
Chaque objet peut avoir trois niveaux de retrait :
- Niveau 1 - Déclaration d’objet
- Niveau 2 - Propriétés de l’objet
- Niveau 3 - Expressions multilignes de propriété d’objet
- Niveau 2 - Propriétés de l’objet
Dans un document TMDL, la mise en retrait est appliquée dans les cas suivants :
Entre un en-tête de section d’objet et les propriétés de l’objet (table -> propriétés).
table Sales isHidden lineageTag: 9a48bea0-e5fb-40fa-9e81-f61288e31a02
Entre un objet et ses objets enfants (table -> mesures).
table Sales measure 'Sales Amount' = SUMX(...) measure 'Total Quantity' = SUM(...)
Entre un objet et ses expressions multilignes (table -> mesure -> expression).
table Sales measure 'Sales Amount' = var result = SUMX(...) return result formatString: $ #,##0
Les expressions multilignes doivent être mises en retrait d’un niveau plus profond que les propriétés de l’objet et l’expression entière doit se trouver dans ce niveau de retrait (voir expressions).
La base de données et les objets enfants directs de Model n’ont pas besoin d’être mis en retrait, car ils sont implicitement supposés imbriqués sous le modèle racine ou la base de données :
- model
- dans des tables
- expressions partagées
- roles
- cultures
- perspectives
- relationships
- sources de données
- groupes de requête
- annotations au niveau du modèle
- propriétés étendues au niveau du modèle
Le fait de ne pas suivre ces règles de retrait génère une erreur d’analyse.
Espace blanc
TMDL applique par défaut les règles suivantes aux espaces blancs dans les valeurs de propriété et d’expression, lorsqu’ils ne sont pas placés dans des backticks (```) ou des guillemets doubles (« ) :
- Sur les valeurs de propriété, les espaces blancs de début et de fin sont supprimés.
- Sur les expressions, les lignes d’espaces blancs à la fin des expressions sont supprimées.
- Les lignes d’espaces blancs sont réduites en lignes vides (pas d’espaces/onglets).
Casse
Par défaut, l’API TMDL sur la sérialisation/écriture utilise camelCase, appliquée à :
- Types d’objets
- Mots clés
- Valeurs d’énumération
Lors de la désérialisation/lecture, l’API TMDL ne respecte pas la casse.
Considérations et limitations
Contenu connexe
Maintenant que vous comprenez TMDL, consultez Prise en main de TMDL pour savoir comment obtenir et déployer une représentation de modèle TMDL d’un modèle Power BI.
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour