[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M699GEZ3YRK8PCPVZF4NEEWF":3,"skill-same:01M699GEZ3YRK8PCPVZF4NEEWF":131},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":44,"ownerDescription":45,"updatedAt":46,"install":47,"resources":60},"01M699GEZ3YRK8PCPVZF4NEEWF","tom-operations",null,"Guide for working with the TOM (Tabular Object Model) wrapper. Use this when modifying semantic models programmatically.","microsoft\u002Fsemantic-link-labs","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M699FKMT63C17BFNH8WHZN2K",596,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ftom-operations\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32],"tom operations","operations","semantic models","model","guide","use","Wrapper","models","semantic","with","object","for","tabular","when","2026-11-10 10:12:30",false,"---\nname: tom-operations\ndescription: Guide for working with the TOM (Tabular Object Model) wrapper. Use this when modifying semantic models programmatically.\n---\n\n# TOM (Tabular Object Model) Operations\n\nThis skill covers working with the TOM wrapper in Semantic Link Labs for programmatic semantic model management.\n\n## When to Use This Skill\n\nUse this skill when you need to:\n- Read or modify semantic model metadata\n- Add\u002Fremove tables, columns, measures, relationships\n- Work with calculation groups and items\n- Manage partitions and data sources\n- Implement model management features\n\n---\n\n## Overview\n\nThe TOM wrapper provides a Pythonic interface to the Tabular Object Model (TOM), which is the object model for Analysis Services semantic models.\n\n### Key Files\n\n| File | Purpose |\n|------|---------|\n| `src\u002Fsempy_labs\u002Ftom\u002F__init__.py` | Module exports |\n| `src\u002Fsempy_labs\u002Ftom\u002F_model.py` | TOMWrapper class implementation |\n\n---\n\n## Basic Usage\n\n### Connecting to a Semantic Model\n\n```python\nfrom sempy_labs.tom import connect_semantic_model\n\n# Read-only connection\nwith connect_semantic_model(\n    dataset=\"My Semantic Model\",\n    readonly=True,\n    workspace=\"My Workspace\"\n) as tom:\n    # Read model metadata\n    for measure in tom.all_measures():\n        print(f\"Measure: {measure.Name}\")\n\n# Read-write connection (requires XMLA read\u002Fwrite enabled)\nwith connect_semantic_model(\n    dataset=\"My Semantic Model\",\n    readonly=False,\n    workspace=\"My Workspace\"\n) as tom:\n    # Modify model\n    measure = tom.model.Tables[\"Sales\"].Measures[\"Revenue\"]\n    measure.Description = \"Total revenue in USD\"\n    # Changes are saved when context exits\n```\n\n### Important Notes\n\n1. **XMLA Endpoint**: Read-write operations require XMLA read\u002Fwrite enabled on the capacity\n2. **Context Manager**: Always use `with` statement - changes are saved on exit\n3. **Service Principal**: Supported via `service_principal_authentication` context\n\n---\n\n## TOMWrapper Properties and Methods\n\n### Core Properties\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # Access the model\n    model = tom.model\n\n    # Get dataset info\n    dataset_id = tom._dataset_id\n    dataset_name = tom._dataset_name\n    workspace_id = tom._workspace_id\n    workspace_name = tom._workspace_name\n\n    # Check compatibility level\n    compat_level = tom._compat_level\n```\n\n### Iterator Methods\n\n| Method | Returns |\n|--------|---------|\n| `all_columns()` | All columns in all tables |\n| `all_calculated_columns()` | All calculated columns |\n| `all_calculated_tables()` | All calculated tables |\n| `all_calculation_groups()` | All calculation groups |\n| `all_measures()` | All measures |\n| `all_partitions()` | All partitions |\n| `all_hierarchies()` | All hierarchies |\n| `all_levels()` | All hierarchy levels |\n| `all_calculation_items()` | All calculation items |\n| `all_functions()` | All user-defined functions |\n\n### Example: Iterating Objects\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # List all measures\n    for measure in tom.all_measures():\n        print(f\"Table: {measure.Parent.Name}, Measure: {measure.Name}\")\n\n    # List all columns\n    for column in tom.all_columns():\n        print(f\"Table: {column.Table.Name}, Column: {column.Name}, Type: {column.DataType}\")\n\n    # List all partitions\n    for partition in tom.all_partitions():\n        print(f\"Table: {partition.Table.Name}, Partition: {partition.Name}\")\n```\n\n---\n\n## Reading Model Metadata\n\n### Tables\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for table in tom.model.Tables:\n        print(f\"Table: {table.Name}\")\n        print(f\"  Description: {table.Description}\")\n        print(f\"  Is Hidden: {table.IsHidden}\")\n```\n\n### Columns\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for column in tom.all_columns():\n        print(f\"Column: {column.Name}\")\n        print(f\"  Table: {column.Table.Name}\")\n        print(f\"  Data Type: {column.DataType}\")\n        print(f\"  Is Hidden: {column.IsHidden}\")\n```\n\n### Measures\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for measure in tom.all_measures():\n        print(f\"Measure: {measure.Name}\")\n        print(f\"  Table: {measure.Parent.Name}\")\n        print(f\"  Expression: {measure.Expression}\")\n        print(f\"  Format String: {measure.FormatString}\")\n```\n\n### Relationships\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for rel in tom.model.Relationships:\n        print(f\"From: {rel.FromTable.Name}[{rel.FromColumn.Name}]\")\n        print(f\"To: {rel.ToTable.Name}[{rel.ToColumn.Name}]\")\n        print(f\"Cross Filter: {rel.CrossFilteringBehavior}\")\n```\n\n---\n\n## Modifying Model Metadata\n\n### Update Measure Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    measure = tom.model.Tables[\"Sales\"].Measures[\"Revenue\"]\n    measure.Description = \"Total revenue\"\n    measure.FormatString = \"$#,##0.00\"\n    measure.DisplayFolder = \"Financial Metrics\"\n```\n\n### Update Column Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    column = tom.model.Tables[\"Date\"].Columns[\"Month\"]\n    column.IsHidden = False\n    column.Description = \"Calendar month\"\n    column.SortByColumn = tom.model.Tables[\"Date\"].Columns[\"MonthNumber\"]\n```\n\n### Update Table Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Sales\"]\n    table.Description = \"Sales transactions\"\n    table.IsHidden = False\n```\n\n---\n\n## Adding Model Objects\n\n### Add a Measure\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Sales\"]\n\n    new_measure = TOM.Measure()\n    new_measure.Name = \"Total Sales\"\n    new_measure.Expression = \"SUM(Sales[Amount])\"\n    new_measure.FormatString = \"$#,##0.00\"\n    new_measure.Description = \"Sum of all sales amounts\"\n\n    table.Measures.Add(new_measure)\n```\n\n### Add a Calculated Column\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Products\"]\n\n    calc_column = TOM.Column()\n    calc_column.Name = \"Profit Margin\"\n    calc_column.Type = TOM.ColumnType.Calculated\n    calc_column.Expression = \"[Revenue] - [Cost]\"\n    calc_column.DataType = TOM.DataType.Decimal\n\n    table.Columns.Add(calc_column)\n```\n\n### Add a Relationship\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    from_column = tom.model.Tables[\"Sales\"].Columns[\"ProductKey\"]\n    to_column = tom.model.Tables[\"Products\"].Columns[\"ProductKey\"]\n\n    relationship = TOM.SingleColumnRelationship()\n    relationship.Name = f\"{from_column.Table.Name}_{to_column.Table.Name}\"\n    relationship.FromColumn = from_column\n    relationship.ToColumn = to_column\n    relationship.CrossFilteringBehavior = TOM.CrossFilteringBehavior.OneDirection\n\n    tom.model.Relationships.Add(relationship)\n```\n\n---\n\n## TOMWrapper Helper Methods\n\nThe TOMWrapper class includes many helper methods for common operations:\n\n### Display Methods (return DataFrames)\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # List all measures\n    df = tom.list_measures()\n\n    # List all columns\n    df = tom.list_columns()\n\n    # List all relationships\n    df = tom.list_relationships()\n\n    # List all partitions\n    df = tom.list_partitions()\n```\n\n### Add Methods\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    # Add measure\n    tom.add_measure(\n        table_name=\"Sales\",\n        measure_name=\"Total Sales\",\n        expression=\"SUM(Sales[Amount])\",\n        format_string=\"$#,##0.00\"\n    )\n\n    # Add calculated column\n    tom.add_calculated_column(\n        table_name=\"Products\",\n        column_name=\"Margin\",\n        expression=\"[Revenue] - [Cost]\"\n    )\n```\n\n### Update Methods\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    # Update measure expression\n    tom.update_measure(\n        table_name=\"Sales\",\n        measure_name=\"Total Sales\",\n        expression=\"SUMX(Sales, Sales[Quantity] * Sales[Price])\"\n    )\n```\n\n---\n\n## Service Principal Authentication\n\n```python\nfrom sempy_labs import service_principal_authentication\nfrom sempy_labs.tom import connect_semantic_model\n\n# Using Service Principal\nwith service_principal_authentication(\n    tenant_id=\"...\",\n    client_id=\"...\",\n    client_secret=\"...\"\n):\n    with connect_semantic_model(\n        dataset=\"My Model\",\n        readonly=False,\n        workspace=\"My Workspace\"\n    ) as tom:\n        # Operations use Service Principal credentials\n        for measure in tom.all_measures():\n            print(measure.Name)\n```\n\n---\n\n## Azure Analysis Services Support\n\nThe TOMWrapper also supports Azure Analysis Services:\n\n```python\nwith connect_semantic_model(\n    dataset=\"MyDatabase\",\n    workspace=\"asazure:\u002F\u002Fwestus2.asazure.windows.net\u002Fmyserver\",\n    readonly=True\n) as tom:\n    for table in tom.model.Tables:\n        print(table.Name)\n```\n\n---\n\n## Best Practices\n\n### Do's\n\n- ✅ Always use context manager (`with` statement)\n- ✅ Use `readonly=True` when only reading metadata\n- ✅ Use iterator methods (`all_measures()`, etc.) for efficient traversal\n- ✅ Save changes by exiting the context normally\n\n### Don'ts\n\n- ❌ Don't open read-write connections when only reading\n- ❌ Don't forget to handle exceptions (changes won't save on exception)\n- ❌ Don't hold connections open longer than necessary\n\n---\n\n## Error Handling\n\n```python\nfrom sempy.fabric.exceptions import FabricHTTPException\n\ntry:\n    with connect_semantic_model(\n        dataset=\"My Model\",\n        readonly=False,\n        workspace=\"My Workspace\"\n    ) as tom:\n        # Modifications...\n        pass\nexcept FabricHTTPException as e:\n    print(f\"API error: {e}\")\nexcept Exception as e:\n    print(f\"Error: {e}\")\n    # Changes NOT saved due to exception\n```\n\n---\n\n## Additional Resources\n\n| Resource | URL |\n|----------|-----|\n| TOM Reference | [Microsoft Docs](https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fapi\u002Fmicrosoft.analysisservices.tabular) |\n| Sample Notebook | [Tabular Object Model.ipynb](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002Fnotebooks\u002FTabular%20Object%20Model.ipynb) |\n| API Documentation | [ReadTheDocs](https:\u002F\u002Fsemantic-link-labs.readthedocs.io\u002Fen\u002Fstable\u002Fsempy_labs.tom.html) |\n","# TOM (Tabular Object Model) Operations\n\nThis skill covers working with the TOM wrapper in Semantic Link Labs for programmatic semantic model management.\n\n## When to Use This Skill\n\nUse this skill when you need to:\n- Read or modify semantic model metadata\n- Add\u002Fremove tables, columns, measures, relationships\n- Work with calculation groups and items\n- Manage partitions and data sources\n- Implement model management features\n\n---\n\n## Overview\n\nThe TOM wrapper provides a Pythonic interface to the Tabular Object Model (TOM), which is the object model for Analysis Services semantic models.\n\n### Key Files\n\n| File | Purpose |\n|------|---------|\n| `src\u002Fsempy_labs\u002Ftom\u002F__init__.py` | Module exports |\n| `src\u002Fsempy_labs\u002Ftom\u002F_model.py` | TOMWrapper class implementation |\n\n---\n\n## Basic Usage\n\n### Connecting to a Semantic Model\n\n```python\nfrom sempy_labs.tom import connect_semantic_model\n\n# Read-only connection\nwith connect_semantic_model(\n    dataset=\"My Semantic Model\",\n    readonly=True,\n    workspace=\"My Workspace\"\n) as tom:\n    # Read model metadata\n    for measure in tom.all_measures():\n        print(f\"Measure: {measure.Name}\")\n\n# Read-write connection (requires XMLA read\u002Fwrite enabled)\nwith connect_semantic_model(\n    dataset=\"My Semantic Model\",\n    readonly=False,\n    workspace=\"My Workspace\"\n) as tom:\n    # Modify model\n    measure = tom.model.Tables[\"Sales\"].Measures[\"Revenue\"]\n    measure.Description = \"Total revenue in USD\"\n    # Changes are saved when context exits\n```\n\n### Important Notes\n\n1. **XMLA Endpoint**: Read-write operations require XMLA read\u002Fwrite enabled on the capacity\n2. **Context Manager**: Always use `with` statement - changes are saved on exit\n3. **Service Principal**: Supported via `service_principal_authentication` context\n\n---\n\n## TOMWrapper Properties and Methods\n\n### Core Properties\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # Access the model\n    model = tom.model\n\n    # Get dataset info\n    dataset_id = tom._dataset_id\n    dataset_name = tom._dataset_name\n    workspace_id = tom._workspace_id\n    workspace_name = tom._workspace_name\n\n    # Check compatibility level\n    compat_level = tom._compat_level\n```\n\n### Iterator Methods\n\n| Method | Returns |\n|--------|---------|\n| `all_columns()` | All columns in all tables |\n| `all_calculated_columns()` | All calculated columns |\n| `all_calculated_tables()` | All calculated tables |\n| `all_calculation_groups()` | All calculation groups |\n| `all_measures()` | All measures |\n| `all_partitions()` | All partitions |\n| `all_hierarchies()` | All hierarchies |\n| `all_levels()` | All hierarchy levels |\n| `all_calculation_items()` | All calculation items |\n| `all_functions()` | All user-defined functions |\n\n### Example: Iterating Objects\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # List all measures\n    for measure in tom.all_measures():\n        print(f\"Table: {measure.Parent.Name}, Measure: {measure.Name}\")\n\n    # List all columns\n    for column in tom.all_columns():\n        print(f\"Table: {column.Table.Name}, Column: {column.Name}, Type: {column.DataType}\")\n\n    # List all partitions\n    for partition in tom.all_partitions():\n        print(f\"Table: {partition.Table.Name}, Partition: {partition.Name}\")\n```\n\n---\n\n## Reading Model Metadata\n\n### Tables\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for table in tom.model.Tables:\n        print(f\"Table: {table.Name}\")\n        print(f\"  Description: {table.Description}\")\n        print(f\"  Is Hidden: {table.IsHidden}\")\n```\n\n### Columns\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for column in tom.all_columns():\n        print(f\"Column: {column.Name}\")\n        print(f\"  Table: {column.Table.Name}\")\n        print(f\"  Data Type: {column.DataType}\")\n        print(f\"  Is Hidden: {column.IsHidden}\")\n```\n\n### Measures\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for measure in tom.all_measures():\n        print(f\"Measure: {measure.Name}\")\n        print(f\"  Table: {measure.Parent.Name}\")\n        print(f\"  Expression: {measure.Expression}\")\n        print(f\"  Format String: {measure.FormatString}\")\n```\n\n### Relationships\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    for rel in tom.model.Relationships:\n        print(f\"From: {rel.FromTable.Name}[{rel.FromColumn.Name}]\")\n        print(f\"To: {rel.ToTable.Name}[{rel.ToColumn.Name}]\")\n        print(f\"Cross Filter: {rel.CrossFilteringBehavior}\")\n```\n\n---\n\n## Modifying Model Metadata\n\n### Update Measure Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    measure = tom.model.Tables[\"Sales\"].Measures[\"Revenue\"]\n    measure.Description = \"Total revenue\"\n    measure.FormatString = \"$#,##0.00\"\n    measure.DisplayFolder = \"Financial Metrics\"\n```\n\n### Update Column Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    column = tom.model.Tables[\"Date\"].Columns[\"Month\"]\n    column.IsHidden = False\n    column.Description = \"Calendar month\"\n    column.SortByColumn = tom.model.Tables[\"Date\"].Columns[\"MonthNumber\"]\n```\n\n### Update Table Properties\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Sales\"]\n    table.Description = \"Sales transactions\"\n    table.IsHidden = False\n```\n\n---\n\n## Adding Model Objects\n\n### Add a Measure\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Sales\"]\n\n    new_measure = TOM.Measure()\n    new_measure.Name = \"Total Sales\"\n    new_measure.Expression = \"SUM(Sales[Amount])\"\n    new_measure.FormatString = \"$#,##0.00\"\n    new_measure.Description = \"Sum of all sales amounts\"\n\n    table.Measures.Add(new_measure)\n```\n\n### Add a Calculated Column\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    table = tom.model.Tables[\"Products\"]\n\n    calc_column = TOM.Column()\n    calc_column.Name = \"Profit Margin\"\n    calc_column.Type = TOM.ColumnType.Calculated\n    calc_column.Expression = \"[Revenue] - [Cost]\"\n    calc_column.DataType = TOM.DataType.Decimal\n\n    table.Columns.Add(calc_column)\n```\n\n### Add a Relationship\n\n```python\nimport Microsoft.AnalysisServices.Tabular as TOM\n\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    from_column = tom.model.Tables[\"Sales\"].Columns[\"ProductKey\"]\n    to_column = tom.model.Tables[\"Products\"].Columns[\"ProductKey\"]\n\n    relationship = TOM.SingleColumnRelationship()\n    relationship.Name = f\"{from_column.Table.Name}_{to_column.Table.Name}\"\n    relationship.FromColumn = from_column\n    relationship.ToColumn = to_column\n    relationship.CrossFilteringBehavior = TOM.CrossFilteringBehavior.OneDirection\n\n    tom.model.Relationships.Add(relationship)\n```\n\n---\n\n## TOMWrapper Helper Methods\n\nThe TOMWrapper class includes many helper methods for common operations:\n\n### Display Methods (return DataFrames)\n\n```python\nwith connect_semantic_model(dataset, workspace=workspace) as tom:\n    # List all measures\n    df = tom.list_measures()\n\n    # List all columns\n    df = tom.list_columns()\n\n    # List all relationships\n    df = tom.list_relationships()\n\n    # List all partitions\n    df = tom.list_partitions()\n```\n\n### Add Methods\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    # Add measure\n    tom.add_measure(\n        table_name=\"Sales\",\n        measure_name=\"Total Sales\",\n        expression=\"SUM(Sales[Amount])\",\n        format_string=\"$#,##0.00\"\n    )\n\n    # Add calculated column\n    tom.add_calculated_column(\n        table_name=\"Products\",\n        column_name=\"Margin\",\n        expression=\"[Revenue] - [Cost]\"\n    )\n```\n\n### Update Methods\n\n```python\nwith connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:\n    # Update measure expression\n    tom.update_measure(\n        table_name=\"Sales\",\n        measure_name=\"Total Sales\",\n        expression=\"SUMX(Sales, Sales[Quantity] * Sales[Price])\"\n    )\n```\n\n---\n\n## Service Principal Authentication\n\n```python\nfrom sempy_labs import service_principal_authentication\nfrom sempy_labs.tom import connect_semantic_model\n\n# Using Service Principal\nwith service_principal_authentication(\n    tenant_id=\"...\",\n    client_id=\"...\",\n    client_secret=\"...\"\n):\n    with connect_semantic_model(\n        dataset=\"My Model\",\n        readonly=False,\n        workspace=\"My Workspace\"\n    ) as tom:\n        # Operations use Service Principal credentials\n        for measure in tom.all_measures():\n            print(measure.Name)\n```\n\n---\n\n## Azure Analysis Services Support\n\nThe TOMWrapper also supports Azure Analysis Services:\n\n```python\nwith connect_semantic_model(\n    dataset=\"MyDatabase\",\n    workspace=\"asazure:\u002F\u002Fwestus2.asazure.windows.net\u002Fmyserver\",\n    readonly=True\n) as tom:\n    for table in tom.model.Tables:\n        print(table.Name)\n```\n\n---\n\n## Best Practices\n\n### Do's\n\n- ✅ Always use context manager (`with` statement)\n- ✅ Use `readonly=True` when only reading metadata\n- ✅ Use iterator methods (`all_measures()`, etc.) for efficient traversal\n- ✅ Save changes by exiting the context normally\n\n### Don'ts\n\n- ❌ Don't open read-write connections when only reading\n- ❌ Don't forget to handle exceptions (changes won't save on exception)\n- ❌ Don't hold connections open longer than necessary\n\n---\n\n## Error Handling\n\n```python\nfrom sempy.fabric.exceptions import FabricHTTPException\n\ntry:\n    with connect_semantic_model(\n        dataset=\"My Model\",\n        readonly=False,\n        workspace=\"My Workspace\"\n    ) as tom:\n        # Modifications...\n        pass\nexcept FabricHTTPException as e:\n    print(f\"API error: {e}\")\nexcept Exception as e:\n    print(f\"Error: {e}\")\n    # Changes NOT saved due to exception\n```\n\n---\n\n## Additional Resources\n\n| Resource | URL |\n|----------|-----|\n| TOM Reference | [Microsoft Docs](https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fapi\u002Fmicrosoft.analysisservices.tabular) |\n| Sample Notebook | [Tabular Object Model.ipynb](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002Fnotebooks\u002FTabular%20Object%20Model.ipynb) |\n| API Documentation | [ReadTheDocs](https:\u002F\u002Fsemantic-link-labs.readthedocs.io\u002Fen\u002Fstable\u002Fsempy_labs.tom.html) |\n",{"name":5,"description":7},"main","2ddf46109c1209ceffa88149f4631e7b2275f9a1",".claude\u002Fskills\u002Ftom-operations",203,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-11 02:21:13",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add microsoft\u002Fsemantic-link-labs --skill tom-operations",{"tool":53,"command":54},"bunx","bunx skills add microsoft\u002Fsemantic-link-labs --skill tom-operations",{"tool":56,"command":57},"pnpm","pnpm dlx skills add microsoft\u002Fsemantic-link-labs --skill tom-operations","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ftom-operations\u002FSKILL.md",true,[61,67,71,75,79,83,87,91,95,99,103,107,113,117,121,127],{"path":62,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":65,"sourceHtmlUrl":66},"assets\u002Ftemplates\u002Fadvanced\u002Fcomposite-action\u002Faction.yml","ASSET","资产文件",8777,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fadvanced\u002Fcomposite-action\u002Faction.yml",{"path":68,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":69,"sourceHtmlUrl":70},"assets\u002Ftemplates\u002Fadvanced\u002Freusable-workflow.yml",9642,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fadvanced\u002Freusable-workflow.yml",{"path":72,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":73,"sourceHtmlUrl":74},"assets\u002Ftemplates\u002Fcd\u002Faws-oidc-deploy.yml",9960,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fcd\u002Faws-oidc-deploy.yml",{"path":76,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":77,"sourceHtmlUrl":78},"assets\u002Ftemplates\u002Fcd\u002Fkubernetes-gitops.yml",11020,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fcd\u002Fkubernetes-gitops.yml",{"path":80,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":81,"sourceHtmlUrl":82},"assets\u002Ftemplates\u002Fcd\u002Fmulti-environment.yml",11500,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fcd\u002Fmulti-environment.yml",{"path":84,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":85,"sourceHtmlUrl":86},"assets\u002Ftemplates\u002Fci\u002Fdocker-build-push.yml",7757,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fci\u002Fdocker-build-push.yml",{"path":88,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":89,"sourceHtmlUrl":90},"assets\u002Ftemplates\u002Fci\u002Fmonorepo-selective.yml",10246,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fci\u002Fmonorepo-selective.yml",{"path":92,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":93,"sourceHtmlUrl":94},"assets\u002Ftemplates\u002Fci\u002Fmulti-language-matrix.yml",8018,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fci\u002Fmulti-language-matrix.yml",{"path":96,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":97,"sourceHtmlUrl":98},"assets\u002Ftemplates\u002Fci\u002Fnode-ci.yml",4979,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fci\u002Fnode-ci.yml",{"path":100,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":101,"sourceHtmlUrl":102},"assets\u002Ftemplates\u002Fci\u002Fpython-ci.yml",6662,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fci\u002Fpython-ci.yml",{"path":104,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":105,"sourceHtmlUrl":106},"assets\u002Ftemplates\u002Fsecurity\u002Fsecurity-scan.yml",12197,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fassets\u002Ftemplates\u002Fsecurity\u002Fsecurity-scan.yml",{"path":108,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":111,"sourceHtmlUrl":112},"references\u002Fperformance-and-troubleshooting.md","REFERENCE","参考文档",10966,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Freferences\u002Fperformance-and-troubleshooting.md",{"path":114,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":115,"sourceHtmlUrl":116},"references\u002Fsecurity-best-practices.md",11914,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Freferences\u002Fsecurity-best-practices.md",{"path":118,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":119,"sourceHtmlUrl":120},"references\u002Fsyntax-quick-reference.md",11232,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Freferences\u002Fsyntax-quick-reference.md",{"path":122,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":125,"sourceHtmlUrl":126},"scripts\u002Fsecurity_audit.py","SCRIPT","脚本",13884,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fscripts\u002Fsecurity_audit.py",{"path":128,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":129,"sourceHtmlUrl":130},"scripts\u002Fvalidate_workflow.py",10088,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002FJamesPrial-github-skills\u002Fgithub-actions-writer\u002Fscripts\u002Fvalidate_workflow.py",[132,161,193,210,224,245],{"skillNo":133,"name":134,"nameZh":6,"description":135,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":136,"categories":137,"keywords":151,"publishedAt":33},"01M699GKE0WWT6YVHBS06KM8AH","write-tests","Guide for writing unit tests. Use this when creating tests to verify Python logic.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fwrite-tests\u002FSKILL.md",[138,143,146],{"categoryNo":139,"categoryName":140,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":144,"categoryName":145,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":147,"categoryName":148,"taxonomyType":149,"taxonomyTypeDesc":150},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[152,153,154,32,155,30,156,157,24,23,158,159,160],"write tests","tests","write","python","unit","logic","verify","unit tests","writing",{"skillNo":162,"name":163,"nameZh":6,"description":164,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":165,"categories":166,"keywords":176,"publishedAt":33},"01M699GGVJHWCJNW68P08VWCMA","ui-styling","Guide for the visual style, structure, and shared building blocks used by Semantic Link Labs interactive UI tools (HTML widgets and anywidget-based widgets). Use this when adding a new interactive UI, modifying an existing one, or adding shared visual components.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fui-styling\u002FSKILL.md",[167,170,173],{"categoryNo":168,"categoryName":169,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":171,"categoryName":172,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":174,"categoryName":175,"taxonomyType":149,"taxonomyTypeDesc":150},"01JBSEEDCAT000000000000032","设计师",[177,178,179,180,23,181,24,182,183,184,185,186,187,188,32,189,30,190,191,192],"styling","ui styling","ui","interactive","components","html","Building Blocks","structure","visual","shared","Tools","widgets","Existing","blocks","visual style","style",{"skillNo":194,"name":195,"nameZh":6,"description":196,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":197,"categories":198,"keywords":205,"publishedAt":33},"01M699GCWWBZM2XFNW5PTGRFJP","sql_to_dax","Guide for translating SQL aggregation expressions into DAX measures.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fsql_to_dax\u002FSKILL.md",[199,202],{"categoryNo":200,"categoryName":201,"taxonomyType":141,"taxonomyTypeDesc":142},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":203,"categoryName":204,"taxonomyType":149,"taxonomyTypeDesc":150},"01JBSEEDCAT000000000000033","数据分析师",[206,207,208,30,209,23],"sql","sql to dax","dax","aggregation",{"skillNo":211,"name":212,"nameZh":6,"description":213,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":214,"categories":215,"keywords":216,"publishedAt":33},"01M699GAY10VVK66E4QGT94A93","run-tests","Guide for running pytest tests locally. Use this when running tests to verify code changes.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Frun-tests\u002FSKILL.md",[],[217,218,153,219,220,158,23,24,221,30,222,32,223],"run","run tests","code","running tests","pytest","changes","running",{"skillNo":225,"name":226,"nameZh":6,"description":227,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":228,"categories":229,"keywords":234,"publishedAt":33},"01M699G8V718EXYE8BR7NX734G","rest-api-patterns","Guide for implementing REST API wrapper functions. Use this when adding new API wrappers or troubleshooting API calls.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Frest-api-patterns\u002FSKILL.md",[230,231],{"categoryNo":200,"categoryName":201,"taxonomyType":141,"taxonomyTypeDesc":142},{"categoryNo":232,"categoryName":233,"taxonomyType":149,"taxonomyTypeDesc":150},"01JBSEEDCAT000000000000030","开发工程师",[235,236,237,238,239,240,241,25,24,23,242,243,244,30,32],"rest api patterns","rest api","patterns","api","api patterns","REST","functions","troubleshooting","calls","implementing",{"skillNo":246,"name":247,"nameZh":6,"description":248,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":249,"categories":250,"keywords":251,"publishedAt":33},"01M699G6XY1WTG7ESA1Y7YYCKT","query-builder-dax","Guide for the DAX query shape produced by the Query Builder in the DAX test widget. Use this when modifying how the Query Builder generates DAX, or when generating an EVALUATE query from columns, measures, filters and sorting.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fsemantic-link-labs\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fquery-builder-dax\u002FSKILL.md",[],[252,208,253,254,255,256,257,32,258,30,259,260,261,262,24,23,263],"query builder","query builder dax","builder","query","test","sorting","evaluate","columns","widget","filters","shape","how"]