关于 tmdl-mastery
面向 Power BI 和 Analysis Services 语义模型开发者的 TMDL 语法与工作流参考技能,涵盖文件结构、序列化、验证和部署。
主要功能
- 01TMDL 语法与对象声明参考
- 02文件夹结构与表达式说明
- 03.NET 序列化 API 示例
- 04语法及元数据验证流程
- 05Power BI Desktop TMDL 视图说明
适用场景
- 01将语义模型纳入源代码管理
- 02通过 TMDL 脚本修改模型
- 03使用 .NET 序列化或反序列化模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill tmdl-mastery安装后在 Claude Code 中输入/tmdl-mastery确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/tmdl-cicd-patterns.mdtmdl-examples-cookbook.mdtmdl-programmatic-python.mdtmdl-syntax-reference.md详细介绍
TMDL(表格模型定义语言)精通
概述
TMDL 参考内容涵盖语言语法、文件夹结构、对象类型、表达式、序列化 API、CI/CD 和部署。TMDL 是一种人类可读且便于进行源代码管理的格式,适用于兼容级别为 1200 及以上的 Power BI 和 Analysis Services 语义模型。
2026 年状态概览
| 方面 | 状态(截至 2026 年 4 月) |
|---|---|
| TMDL 语言 GA | 自 2024 年 8 月起正式发布(GA)——不再是预览版 |
| Power BI Desktop 中的 TMDL 视图 | 正式发布(GA)——支持语义突出显示、自动补全、代码操作、差异预览和兼容性提示 |
| TMDL 作为默认 PBIP 语义模型格式 | 默认格式——model.bim 是旧版 BIM 格式;新建 PBIP 项目会写入 definition/*.tmdl 文件 |
| Fabric Git 集成 | 将语义模型导出为 TMDL(而非 TMSL/BIM) |
| TMSL / BIM | 未弃用——仍支持 XMLA 脚本命令,以及需要 JSON 的工具。源代码管理使用 TMDL,XMLA createOrReplace 命令脚本使用 TMSL |
| 兼容级别 | 推荐使用 1550+;某些较新的属性(例如 formatStringDefinition、计算组多选/空选表达式)要求 1601+ |
| Tabular Editor 2(免费) | 支持 TMDL 读写(2.17+) |
| Tabular Editor 3(付费) | 提供完整的 TMDL IDE,包含 DAX 调试器和关系图视图 |
| VS Code TMDL 扩展 | Microsoft 的 analysis-services.TMDL 和社区扩展 CPIM.TMDL-language-support(支持 DAX + M 突出显示、代码操作、格式化和面包屑导航) |
| Report Server | 不支持 TMDL——继续使用旧版 PBIX 二进制格式 |
要点: 对于纳入源代码管理的新 Power BI / Fabric 语义模型,请使用 TMDL。对于 XMLA 脚本或需要 model.bim 的工具,请保留 TMSL。
TMDL 与 TMSL 和 BIM 的对比
| 方面 | TMDL(.tmdl 文件夹) | TMSL / BIM(model.bim) |
|---|---|---|
| 格式 | 类 YAML 文本,基于缩进 | 单个 JSON 文件 |
| 文件 | 每个表、角色、区域性和透视图各一个文件 | 单体文件 |
| Git 友好性 | 极佳——差异粒度细,合并冲突少 | 较差——整个模型都在一个差异中 |
| 可读性 | 高——分隔符少,内嵌 DAX/M | 低——JSON 字符串需要转义 |
| 工具支持 | VS Code 扩展、Desktop 中的 TMDL 视图、Tabular Editor 3 | 任意 JSON 编辑器、Tabular Editor 2/3 |
| API | TmdlSerializer(.NET) | JsonSerializer(.NET)、TMSL 命令 |
| 迁移 | 可通过 Tabular Editor 或 Desktop 从 BIM 转换 | 默认旧版格式 |
何时使用 TMDL: 任何新的、纳入源代码管理的 CI/CD 或团队 PBIP 项目。
何时使用 TMSL/BIM: 旧版项目、Report Server(不支持 TMDL)或仅接受 BIM 的工具。
对象声明语法
声明对象时,先指定 TOM 对象类型,再指定其名称:
model Model
culture: en-US
table Sales
measure 'Sales Amount' = SUM(Sales[Amount])
formatString: $ #,##0
column 'Product Key'
dataType: int64
sourceColumn: ProductKey
summarizeBy: none
主要规则:
- 如果名称包含点、等号、冒号、单引号或空白字符,请用单引号括起
- 名称中的单引号需通过重复书写进行转义:
'My ''Special'' Table' - 子对象通过缩进隐式嵌套在其父对象下(无需显式集合)
- 子对象不必连续排列——列和度量值可以自由交错
属性语法
属性使用冒号作为分隔符;表达式使用等号作为分隔符:
column Category
dataType: string /// colon for non-expression properties
sortByColumn: 'Cat Order' /// colon for object references
isHidden /// boolean shortcut (true implied)
isAvailableInMdx: false /// explicit boolean
measure Total = SUM(Sales[Amount]) /// equals for default expression
formatString: $ #,##0 /// colon for properties after expression
文本属性值: 开头和结尾的双引号可省略,也会自动去除。如果值开头或结尾包含空白字符,则必须使用双引号。内部双引号需通过重复书写进行转义。
按对象类型划分的默认属性
| 对象类型 | 默认属性 | 语言 |
|---|---|---|
| measure | Expression | DAX |
| calculatedColumn | Expression | DAX |
| calculationItem | Expression | DAX |
| partition (M) | Expression | M |
| partition (calculated) | Expression | DAX |
| tablePermission | FilterExpression | DAX |
| namedExpression | Expression | M |
| annotation | Value | Text |
| jsonExtendedProperty | Value | JSON |
默认属性使用等号(=),可以写在同一行,也可以作为多行表达式写在后续行中。
表达式——单行和多行
/// Single-line expression
measure 'Sales Amount' = SUM(Sales[Amount])
/// Multi-line expression (indented one level deeper than parent properties)
measure 'YoY Growth %' =
VAR CurrentSales = [Sales Amount]
VAR PYSales = CALCULATE([Sales Amount], SAMEPERIODLASTYEAR('Date'[Date]))
RETURN DIVIDE(CurrentSales - PYSales, PYSales)
formatString: 0.00%
/// Triple-backtick block for verbatim content (preserves whitespace exactly)
partition 'Sales-Part' = m
mode: import
source = ```
let
Source = Sql.Database("server", "db"),
Sales = Source{[Schema="dbo",Item="Sales"]}[Data]
in
Sales
```
表达式规则:
- 多行表达式的缩进比父属性多一级
- 除非使用三反引号代码块,否则会删除行尾空格
- 三反引号代码块会保留空白;结束定界符决定左边界
描述(/// 语法)
/// This table contains all sales transactions
/// Updated daily via incremental refresh
table Sales
/// Total revenue across all product lines
measure 'Sales Amount' = SUM(Sales[Amount])
对象上方的三斜杠注释会成为其 TOM Description 属性。描述块与对象类型关键字之间不能有空白。
Ref 关键字
引用另一个 TMDL 对象或定义集合排序:
/// In model.tmdl -- defines table ordering for deterministic roundtrips
model Model
culture: en-US
ref table Calendar
ref table Sales
ref table Product
ref table Customer
ref culture en-US
ref culture pt-PT
ref role 'Regional Manager'
规则: 反序列化时,会忽略已引用但缺少对应文件的对象。有文件但没有 ref 的对象会追加到集合末尾。
TMDL 文件夹结构
definition/
database.tmdl # Database properties (compatibilityLevel, etc.)
model.tmdl # Model properties, ref declarations
relationships.tmdl # All relationships
expressions.tmdl # Shared/named expressions (Power Query parameters)
functions.tmdl # DAX user-defined functions
dataSources.tmdl # Legacy data sources
tables/
Sales.tmdl # Table + all its columns, measures, partitions, hierarchies
Product.tmdl
Calendar.tmdl
roles/
RegionalManager.tmdl # Role definition with permissions and members
Admin.tmdl
cultures/
en-US.tmdl # Translations for all objects in this culture
pt-PT.tmdl
perspectives/
SalesView.tmdl # Perspective definition
每个表、角色、区域性设置和透视各使用一个文件。所有内部元数据(列、度量值、分区、层次结构)都位于父表文件中。
TMDL 脚本(createOrReplace)
使用 Power BI Desktop 中的 TMDL 视图,将更改应用于实时语义模型:
createOrReplace
table 'Time Intelligence'
calculationGroup
precedence: 1
calculationItem Current = SELECTEDMEASURE()
calculationItem YTD =
CALCULATE(SELECTEDMEASURE(), DATESYTD('Calendar'[Date]))
calculationItem PY =
CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('Calendar'[Date]))
column 'Time Calc'
dataType: string
sourceColumn: Name
sortByColumn: Ordinal
column Ordinal
dataType: int64
sourceColumn: Ordinal
summarizeBy: none
每次脚本执行只能使用一个命令动词。createOrReplace 命令会创建或替换指定对象及其所有后代对象。
缩进规则
TMDL 使用严格的空白缩进,默认每级缩进一个 制表符:
- 第 1 级: 对象声明(
table、measure、column) - 第 2 级: 对象属性(
dataType、formatString) - 第 3 级: 多行表达式(DAX/M 代码)
数据库级和模型级的直接子级(table、relationship、role、culture、perspective、expression)无需缩进,因为它们隐含地位于根级之下。缩进不正确会导致 TmdlFormatException。
大小写和空白
- 序列化对对象类型、关键字和枚举值使用 camelCase
- 反序列化时 不区分大小写
- 属性值开头和结尾的空白会被去除
- 表达式末尾的空行会被删除
- 表达式中的纯空白行会保留为空行
TMDL 序列化 API(.NET)
using Microsoft.AnalysisServices.Tabular;
// Serialize model to TMDL folder
TmdlSerializer.SerializeDatabaseToFolder(database, @"C:\output\model-tmdl");
// Deserialize TMDL folder back to TOM
var db = TmdlSerializer.DeserializeDatabaseFromFolder(@"C:\output\model-tmdl");
// Serialize single object to string
string tmdl = TmdlSerializer.SerializeObject(table.Measures["Total Sales"]);
NuGet 包: Microsoft.AnalysisServices.NetCore.retail.amd64(或对应的 .NET Framework 版本)
错误类型: TmdlFormatException(语法无效)和 TmdlSerializationException(语法有效,但 TOM 元数据无效)。两者都包含 Document、Line 和 LineText 属性。
自我验证
部署生成的任何 TMDL 之前,请运行 powerbi-master:validation-testing 技能提供的四层验证流程:
- 语法——
TmdlSerializer.DeserializeDatabaseFromFolder会捕获TmdlFormatException(缩进错误、关键字无效) - 元数据——同一调用会捕获
TmdlSerializationException(属性组合无效),而model.Validate()会捕获悬空引用 - 最佳实践——Tabular Editor 2 CLI 的
-A开关或semantic-link-labs.run_model_bpa会运行标准 Microsoft BPA 规则集 - 血缘关系——
model.Validate().Errors加上自定义 Tabular Editor C# 脚本,可捕获 sortByColumn / 度量值引用列的问题
validation-testing 技能为每一层提供可直接运行的示例(C#、Python、GitHub Actions YAML)。推荐部署前务必进行验证。
Power BI Desktop 中的 TMDL 视图(2026)
TMDL 视图是 Power BI Desktop 中集成的代码编辑器,用于通过脚本编写语义模型更改。截至 2026 年发布周期,其功能包括:
- 语义高亮、自动补全(Ctrl+Space)、悬停提示和代码操作(生成沿袭标记、纠正属性拼写错误)
- 代码格式化,可通过 Shift+Alt+F 或功能区中的“格式”按钮进行(包括通过上下文菜单使用“格式化所选内容”)
- 错误诊断,并提供专用的“问题”窗格
- 预览差异 —— 并排或内联显示执行脚本前后的模型 TMDL 差异,可通过工具栏导航(预览运行仅支持有效的 TMDL)
- 兼容性级别升级提示 —— 如果脚本使用的属性高于当前模型兼容性级别(例如,为
formatStringDefinition从 1550 升级到 1601),Desktop 会提示自动升级 - 多标签页脚本,保存在 PBIP 项目的
TMDLScripts/文件夹中(每个标签页对应一个文件) - 将对象从“数据”窗格拖到编辑器中,即可将其编写为
createOrReplace;拖动前按住 Ctrl 可多选 - 右键单击 > 编写 TMDL 脚本,可将脚本发送到新标签页或剪贴板
- 应用按钮可应用仅元数据更改(不刷新数据);通过 TMDL 重命名列会使其与
sourceColumn脱离关联(Power Query 编辑器仍显示源名称) - 通过正则表达式查找和替换批量重命名 —— 常见用途包括移除前缀(
fact_、dim_)或更改大小写
限制: Desktop 不会热重载从外部更改的 TMDL 文件。在 VS Code 中编辑 .tmdl 文件后,请重启 Power BI Desktop 以加载更改。
Semantic Link Labs(Fabric 笔记本中的 Python TOM)
若要在没有 .NET 工具链的情况下通过 Python 编写语义模型脚本,请在 Fabric 笔记本中使用 semantic-link-labs(PyPI:semantic-link-labs)。它提供了 TOM 的 Python 风格封装:
%pip install semantic-link-labs -q
import sempy_labs as labs
from sempy_labs.tom import connect_semantic_model
with connect_semantic_model(dataset="SalesModel", workspace="Sales-Dev", readonly=False) as tom:
# Add a measure
tom.add_measure(
table_name="Sales",
measure_name="Sales Amount",
expression="SUM(Sales[Amount])",
format_string="$ #,##0.00",
display_folder="Revenue",
)
# Add an incremental refresh policy
tom.add_incremental_refresh_policy(
table_name="Sales",
column_name="OrderDate",
start_date="2020-01-01T00:00:00",
end_date="2025-12-31T00:00:00",
incremental_granularity="Day",
incremental_periods=30,
rolling_window_granularity="Month",
rolling_window_periods=36,
)
# tom.save_changes() is called automatically on context exit
完整操作指南请参阅 references/tmdl-programmatic-python.md。
其他资源
参考文件
references/tmdl-syntax-reference.md—— 完整的 TMDL 语法和语法规则参考,涵盖所有对象类型、属性和表达式规则references/tmdl-examples-cookbook.md—— 每种对象类型的可复制粘贴 TMDL 示例:表、列、度量值、分区、关系、角色、透视、区域性、计算组、层次结构、KPI、注释和字段参数references/tmdl-cicd-patterns.md—— CI/CD 管道、Git 集成、部署模式、Tabular Editor CLI、Azure DevOps 和 GitHub Actions 工作流,以及合并冲突策略references/tmdl-programmatic-python.md—— 在 Fabric Python 笔记本中使用 semantic-link-labs / SemPy 编写 TOM 脚本:度量值、计算组、增量刷新、RLS、Direct Lake、BPA 和模型导出模式
相关技能
powerbi-master:validation-testing—— 在部署前验证 TMDL 构件:TmdlSerializer 解析器、TOM Validate、通过 Tabular Editor CLI / semantic-link-labs 使用 BPA、自定义 C# 规则脚本
Microsoft Learn 官方参考(2026)
- 宣布 TMDL 正式发布 —— TMDL 正式发布公告
- 在 Power BI Desktop 中使用 TMDL 视图 —— 功能场景介绍
- Power BI Desktop 项目语义模型文件夹 —— PBIP 中的 TMDL
- TMDL 脚本参考(Microsoft Learn) ——
createOrReplace命令文档