tabulareditor / bestpracticerules Goto Github PK
View Code? Open in Web Editor NEWAn official collection of standard Rules for use with Tabular Editor's Best Practice Analyzer.
An official collection of standard Rules for use with Tabular Editor's Best Practice Analyzer.
The Rule "Avoid CamelCase on visible measures and tables" (BPA-Standard) is checking for the first letter being upper case. That would be PascalCasing and not camelCasing. in camelCasing the first letter is lower case.
"ID": "META:_COLUMNS_THAT_ARE_VISIBLE_AND_INT64_SHOULD_BE_SET_TO_DO_NOT_SUMMARIZE",
"Name": "META: Attributes that are visible and Int64 should be set to do not summarize",
"Category": null,
"Description": "Attributes that are vissible and their data type is Int 64 need to be set to DO NOT SUMMARIZE. DO NOT SUMMARIZE is one of the 'Reporting Properties' in Visual Studio ('Other' in Tabular Editor) and is found under 'Summarize By'.",
"Severity": 3,
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
"ScopeString": "Columns",
"Expression": "DataType.ToString().Equals(\"Int64\") and !SummarizeBy.ToString().Equals(\"None\") and not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
This rule would check for null descriptions and for those found copy the Expression into the Description.
For deployed models, this would be a starting point to give visibility to users of what calculations are being made in the measure, calculated column, or calculated table.
Some DAX functions require the IsAvailableInMDX property to be true, though documentation as to which functions require it is poor.
In order for the function PATH to work, both the parent and child column it references must have this property set to true. I've added one additional filter to the expression to exempt such columns from being flagged.
Relevant rule addition:
and not ReferencedBy.AllColumns.Any(Expression.Contains(\"PATH(\"))
Full rule definition:
{
"ID": "DISABLE_ATTRIBUTE_HIERACHIES",
"Name": "Disable attribute hierachies to decrease processing",
"Category": "Metadata",
"Description": "Disable Attribute hierarchies for hidden collumns. This will ensure faster processing. Exclude columns used in PATH function.",
"Severity": 2,
"Scope": "DataColumn",
"Expression": "not IsVisible\r\nand IsAvailableInMDX\r\nand not UsedInHierarchies.Any()\r\nand not UsedInVariations.Any()\r\nand not UsedInSortBy.Any()\r\nand not ReferencedBy.AllColumns.Any(Expression.Contains(\"PATH(\"))",
"FixExpression": "IsAvailableInMDX = false",
"CompatibilityLevel": 1400,
"Source": "standard\\Metadata"
}
From @marcosqlbi on November 8, 2017 2:30
If a user belongs to two roles applying filters on the same table with row level security (RLS) in one role, and object level security in another role (OLS), the connection is not possible by design.
you can’t have RLS and OLS on the same table in different roles – that would prevent the connection from being opened
A Best Practices Analyzer rule could identify the presence or roles applying different filter types (RLS/OLS) over the same tables. If the developer knows that this will never happen (because a user cannot belong to two incompatible roles), there should be a way to disable the BPA (what could we use for that? Special annotations?).
Copied from original issue: TabularEditor/TabularEditor#113
Hi,
Is it possible to exclude comments in calculated items (measures, columns, tables etc.)? We use them allot to give some extra context when needed.
For example
SUMMARIZECOLUMNS (
'Sales'[Posting Date],
'Sales'[Customer No],
'Sales'[Item No],
'Sales'[VAT Rate],
'Sales'[Currency Code],
/* Makes sure that issues with currency conversions are filtered out. */
FILTER ( 'Sales', 'Sales'[Selling Price (EUR)] < 1000 )
)
hI
When running the Tabular Editor by command line and using the Best Practice anlayser
I get this
Deployment failed! DAX comparison operations do not support comparing values of type Integer with values of type True/False. Consider using the VALUE or FORMAT function to convert one of the values.
I understand the error its just I was unable to tie this back to the rule that triggered it - couldnt see it referenced in Dev ops
We are downloading the latest version of Tabular Editor each time using a ps script - I do know the build version - Tabular Editor 2.12.4 (build 2.12.7563.29301)
I made sure all the rules from the git hub site were up to date but i coudnt see this rule
Could you assist?
Ronan
Your DBA's will love it. It will help them to find heavy queries.
"ID": "META:_FOREIGN_KEYS_&_PRIMARY_KEYS_HAVE_THE_SAME_NAME",
"Name": "META: Foreign Keys & Primary Keys should have the same name",
"Category": null,
"Description": "Foreign Keys & Primary Keys should have the same name.",
"Severity": 3,
"Scope": "Relationship",
"ScopeString": "Relationships",
"Expression": "!FromColumn.Name.ToLower().Equals(ToColumn.Name.ToLower())",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
I'm not sure if this is a more of a BPA feature suggestion or a BPA Rule suggestion, but I think this could be done in the rule expression. We are utilizing Git for our CI/CD process and we invoke TE3 via CLI in Git to run the BPA to check before we allow a PR to be created or merged.
Because each model is different and will therefore have it's own exceptions to the rules, can we put every existing rule's LINQ script inside of a "wrapper" that checks to see if the rule should apply to this particular model and then exit if it doesn't?
//Wrapper Pseodo-code
IF Model.Name IN (array of model's to be ignored for this rule)
EXIT
ELSE
run regular LINQ script
END IF
Hi Daniel,
I'm impressed by your presentation of Tabular Editor. It's definitely a key tool in Power BI environment. Congratulation again !
As you know, I work on automatic translations and I got already some good results. So I was very interrested in the rule about "Translate display folders" but I think there is a bug there. As you can see on the screenshot, the rule reports some translations are missing but in the column or measure the properties reports "0 empty".
Additionaly, after I added the standard rules as you demonstrated in the video, opening the bim file takes now a lot of time. The bim file is attached
Thanks in advance
Every visible measure should have format string. Automatic number of decimals is a warning, because it is likely to be wrong.
"ID": "PERF:_USED_IN_RELATIONSHIPS",
"Name": "PERF: Key columns should be used in Relationships",
"Category": null,
"Description": "Don't include key columns that are not used for creating relationships unless they have special use.",
"Severity": 3,
"Scope": "DataColumn",
"ScopeString": "Data Columns",
"Expression": "((Name.ToLower().EndsWith(\"id\") or Name.ToLower().EndsWith(\"key\")))\nand (not UsedInRelationships.Any())",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
is there a way to create a rule to detect which fact table columns generate a referential integrity on any particular dimension?
Looks like the Vertipaq Analyzer provides the count of RI's for each dimension, but no info on the offending fact tables.
Also, trying to use this query below, also does not surface the fact tables:
select
[Database_name] ,
[Dimension_Name] ,
[RIVIOLATION_COUNT]
from $SYSTEM.DISCOVER_STORAGE_TABLES
WHERE
[RIVIOLATION_COUNT] > 0
thank you kindly,
Cosmin
Good morning,
Firstly, I really like the effort the communities to elevate the Power BI development level. Keep up the good job.
I'm trying for the first time the BPA and struggling with the rule "Hide foreign key columns". I'm also new to LINQ.
I've paste the below formula found here (https://docs.tabulareditor.com/Best-Practice-Analyzer.html#fixing-objects)
"Model.Relationships.Any(FromColumn = outerIt) and not IsHidden and not Table.IsHidden"
and I got the error message "Operator '=' incompatible with operand types "Column" and Model""
Thanks in advance for letting me know.
Kind regards,
Lohic Beneyzet
Use names such as "Sales Amount" instead of "SalesAmount"
{
"ID": "DISABLE_AUTO_TIME_INTELLIGENCE",
"Name": "Disable auto time intelligence",
"Category": "Performance",
"Description": "Remove hidden auto date/time tables and disable the Current File's Auto date/time."
"Severity": 3,
"Scope": "Model",
"Expression": "Tables.Any(Name.StartsWith("LocalDateTable_"))"
"FixExpression": "__PBI_TimeIntelligenceEnabled = 0"
}
Hi
The rule Disable Attribute Hierarchies should have a minimum compatibility level of 1470 as this is only available in SSAS 2017 after SP2
{
"ID": "DISABLE_ATTRIBUTE_HIERACHIES",
"Name": "Disable attribute hierachies to decrease processing",
"Category": "Metadata",
"Description": "Disable Attribute hierarchies for hidden collumns. This will ensure faster processing.",
"Severity": 2,
"Scope": "DataColumn",
"Expression": " IsHidden \n\nand (IsAvailableInMDX == TRUE)\n\nand (not UsedInHierarchies.Any())",
"FixExpression": "IsAvailableInMDX = false",
"CompatibilityLevel": 1470
}
Columns and calculated columns must have a datatype other than 'Any'.
I think this rule should be restricted to only work on numeric columns, as the rule name implies.
Also, hidden tables should be excluded. There is already a condition to exclude hidden columns, but this is not sufficient, because columns in hidden tables are marked as visible unless explicitly hidden (which is redundant).
I think this issue can be solved by using the following rule expression:
IsHidden = false
and Table.IsHidden = false
and SummarizeBy <> "None"
and (DataType = "Double" or DataType = "Decimal" or DataType = "Int64")
"ID": "META:_VISIBLE_MEASURE_NEED_TO_HAVE_FORMATTING",
"Name": "META: Visible Measure need to have formatting",
"Category": null,
"Description": "Visible Measure need to have specific formatting and should not default to General",
"Severity": 3,
"Scope": "Measure",
"ScopeString": "Measures",
"Expression": "(String.IsNullOrWhiteSpace(FormatString)) and not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
"ID": "DATABASE_CONNECTION_MUST_BE_WITH_SPECIFIC_'DATABASENAME'_&_SERVERS_IN('SERVER1','SERVER2','SERVER3','SERVER4','SERVER3,60793')",
"Name": "META: Database connection must be with specific 'DatabaseName' & specific servers only",
"Category": null,
"Description": "All the cube data comes from a single database named source, DatabaseName, in these servers (Server1, Server3, Server3,60793, Server2, Server4, abivmscentral66). If you have data coming other than from these list of servers and database name, please check and get from these list of servers and database only. If you can't get the data in these servers/database contact the database team.",
"Severity": 10,
"Scope": "DataSource",
"ScopeString": "Data Sources",
"Expression": "!Name.ToLower().Equals(\"sqlserver Server1 DatabaseName\")\nand !Name.ToLower().Equals(\"sqlserver Server3 DatabaseName\")\nand !Name.ToLower().Equals(\"sqlserver Server3,60793 DatabaseName\")\nand !Name.ToLower().Equals(\"sqlserver Server2 DatabaseName\")\nand !Name.ToLower().Equals(\"sqlserver Server4 DatabaseName\")\nand !Name.ToLower().Equals(\"sqlserver abivmscentral66 DatabaseName\")",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
I'm running the BPA on a variety of models, and looking to create a living catalog of violations, fixes, exceptions/ignores. A simple 'export to Excel' feature may help, so that models owners can make annotations when fixes are applied, exceptions are made or rules are added/dropped. An inline tracking/cataloging feature within Tabular Editor might fit the bill too, but likely a taller order.
"ID": "NAME:_ATTRIBUTE_NAMES_SHOULDN'T_HAVE_'_'_'/'_'\\'",
"Name": "NAME: Attribute names should not have '_' '/' '\\'",
"Category": null,
"Description": "Attribute names should not contain these special characters '_' '/' '\\' You may use camel case or spaces instead for readability.",
"Severity": 3,
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
"ScopeString": "Columns",
"Expression": "(Name.Contains(\"_\") or Name.Contains(\"\\\") or Name.Contains(\"/\")) and not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
Define Detail Rows if a measure depends on one or more other measures that have Detail Rows property defined.
Hi
I need to create a rule to check whether a filter condition has been used in calculate to filter a column.
Lets say there is a fact table called Sales and it has an amount column and another column for category which has 4-5 different categories in it. Let’s say I would like to calculate sales amount for a certain category from the category column. There are 2 ways of writing a measure that filters a category column for a certain condition:-
Measure 1 = Calculate(Sum('Sales'[Amount]),'Sales'[Category]="Red")
Measure 2 = Calculate(Sum('Sales'[Amount]),Filter(' Sales ', Sales '[Category]="Red"))
Both measure are correct but measure 2 takes longer time and will eventually slowdown visual rendering. As per marco russo filter function shall never be used for filtering a column. I need to create a rule that checks If any measure in the model is doing it if yes than I would like to highlight it.
Regards
Currently set to diable auto date/time. > Should be Disable Auto Date/Time
"ID": "META:_FOREIGN_AND_PRIMARY_KEYS_SHOULD_BE_INT",
"Name": "META: Foreign and Primary Keys should be INT",
"Category": null,
"Description": "Foreign and Primary Keys should be INT data type. ",
"Severity": 3,
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
"ScopeString": "Columns",
"Expression": "(Name.ToLower().EndsWith(\"id\") or Name.ToLower().EndsWith(\"key\"))\nand !DataType.ToString().Equals(\"Int64\")",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
I think this rule should not be applied to measures, because there is no way of changing the data type of measures by changing the metadata, as far as I'm aware.
In fact, if you try to apply a fix, you will get the following error:
Also, for clarity purposes, I would change the description from:
Floating point datatypes can cause unexpected results when evaluating values close to 0. Use Decimal instead.
To something like this:
Floating point datatypes can cause unexpected results when evaluating values close to 0. Use Currency / Fixed Decimal Number (decimal) instead.
Because in Visual Studio, the floating point data type is called Decimal Number, which could be confusing when people are instructed to "use Decimal instead".
"ID": "LAYOUT:_FORMAT_MEASURES_IN_ONE_OF_THE_SET_OF_PREDEFINED_FORMATS_FOR_THE_CUBE
",
"Name": "LAYOUT: Format Measures in one of the set of predefined formats for the cube",
"Category": null,
"Description": "Measure formatting should be one of these: currency no decimals, percentage with comma & 1 or 2 decimals, whole number with comma & no decimals, decimal with comma & 1 decimal.",
"Severity": 10,
"Scope": "Measure",
"ScopeString": "Measures",
"Expression": "(!FormatString.Equals("\$#,0;(\$#,0);\$#,0") \nand !FormatString.Equals("#,0.0 %;-#,0.0 %;#,0.0 %")\nand !FormatString.Equals("#,0.00 %;-#,0.00 %;#,0.00 %")\nand !FormatString.Equals("0.0 %;-0.0 %;0.0 %")\nand !FormatString.Equals("0.00 %;-0.00 %;0.00 %")\nand !FormatString.Equals("\$#,0.0;(\$#,0.0);\$#,0.0")\nand !FormatString.Equals("#,0.0")\nand !FormatString.Equals("0.0")\nand !FormatString.Equals("0")\nand !FormatString.Equals("#,0")) and not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
The names of the columns involved in a relationships should be the same, unless there are more relationships to the same table (e.g. Order Date, Start Date).
"ID": "LAYOUT:_HIDE_FACT,_BRIDGE_OR_USER_TABLES",
"Name": "LAYOUT: Hide Fact, Bridge or User tables",
"Category": null,
"Description": "Fact, Bridge or User tables should be hidden. Right click the table name and select 'Hide from Client Tools'",
"Severity": 3,
"Scope": "Table",
"ScopeString": "Tables",
"Expression": "(Name.ToLower().Contains(\"bridge\") or Name.ToLower().Contains(\"fact\") or Name.ToLower().Contains(\"user\"))\nand not IsHidden\n",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
Connection strings should not contain SQLOLEDB or SQLNCLI. It should be changed to MSSQLOLEDB. Source : https://docs.microsoft.com/en-us/sql/connect/oledb/oledb-driver-for-sql-server?view=sql-server-2017
Hi!
I have loaded and used BPA rules from Github previously but am unable to neither load rules through your C# snippet or add physical file in the tabular editor folder since lately. I have tried both adding the file through "Create new rule file" and "Include local rule file" to no avail.
No matter which route I take the BPA Rules JSON file in the program folder empties out with the exception of two brackets [ ] making the file 1kb small instead of the ~35kb size I add.
How can I fix this?
Hi Daniel,
I want to check if a column is sorted by another column. What expression would do it?
I've tried "IsHidden = false and sortByColumn <> null" but it did not work. Can you help me out here, please?
Thanks in advance.
Dominik
Measures comprised of a text value don't need a format string.
A rule that detects if a calculation item expression holds references the calculation group itself in the DAX expression (this indicates a sideways recursion which should be avoided).
Sounds stupid until you find out how many tables you have without a rowidentifier/key
"ID": "META:_MEASURE_NAMES_SHOULDN'T_HAVE_'_'_'/'_'\\'",
"Name": "META: Measure names should not have '_' '/' '\\'",
"Category": null,
"Description": "META: Measure names should not have '_' '/' '\\'",
"Severity": 2,
"Scope": "Measure",
"ScopeString": "Measures",
"Expression": "Name.Contains(\"_\") or Name.Contains(\"\\\") or Name.Contains(\"/\") and not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
Hi
Hidden columns should have Avaliable In MDX disabled to optimize processing time
{
"ID": "DISABLE_ATTRIBUTE_HIERACHIES",
"Name": "Disable attribute hierachies to decrease processing",
"Category": "Metadata",
"Description": "Disable Attribute hierarchies for hidden collumns. This will ensure faster processing.",
"Severity": 2,
"Scope": "DataColumn",
"Expression": " IsHidden \n\nand (IsAvailableInMDX == TRUE)\n\nand (not UsedInHierarchies.Any())",
"FixExpression": "IsAvailableInMDX = false"
}
"ID": "META:_PARTITION_NAME_SHOULD_MATCHE_TABLE_NAME",
"Name": "META: Match Partition Name & Table Name",
"Category": null,
"Description": "Partition Name should match Table Name.",
"Severity": 10,
"Scope": "Partition",
"ScopeString": "Partitions",
"Expression": "!Name.Equals(Table.Name) and Table.Partitions.Count()==1",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
In TE 3 there is a feature which immediately warns me about any expression, which uses non fully qualified columns. Would be nice to have that in BPA as well.
"ID": "LAYOUT:_KEY_COLUMNS_SHOULD_BE_HIDDEN
",
"Name": "LAYOUT: Key columns should be hidden",
"Category": null,
"Description": "Key columns that are used as Primary and foreign keys should be hidden from clients.",
"Severity": 3,
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
"ScopeString": "Columns",
"Expression": "(Name.ToLower().EndsWith("id") or Name.ToLower().EndsWith("key"))\nand not IsHidden",
"FixExpression": null,
"Compatibility": null,
"IsValid": false
I added the following Rule to my BPA. I don't want my users to connect to the model directly and instead use one of the perspective. Therefore I need to make sure that all measures and columns are added to at least 1 perspective.
I use the following:
IsVisible and Model.Perspectives.Any() and not InPerspective.Any(it)
The current rule does not take into account the following situations where a slash is, in my opinion, legitimate:
My Measure := [$] /* This is just for illustration purposes */
Net Profit := CALCULATE ( [$], 'Measure Hierarchy'[Name] = "Net gain/(loss)" )
Only Yes := CALCULATE ( [$], Dim[Yes/No] = "Yes" )
Monthly Revenue := Sales[Yearly Revenue] / 12
I managed to address the first situation by adding one more condition:
and (not Expression.Contains("/*"))
Unfortunately, my Dynamic LINQ skills are close to nil, and I don't know how to address the other situations. Also, I understand that my solution to the first situation is not ideal because it excludes cases where there is both a multi-line comment and a genuine division that should be avoided.
Avoid using prefixes and camelCasing. Use "Sales" instead of "dimSales" or "mSales".
Here is a rule that I often find in models due to over normalization of tables. These generally crop up due to snowflaking in the underlying database schema. Note, I exclude hidden and key columns from the count.
{
"ID": "NO_SINGLE_COLUMN_SINGLE_RELATION_TABLES",
"Name": "No single column, single relation tables",
"Category": "Performance",
"Description": "Single column tables that only participate in a single relationship are unnecessary. Fold the attributes into the related table. Note, hidden and key columns are excluded.",
"Severity": 1,
"Scope": "Table",
"Expression": "not IsHidden and Columns.Count(not Name.EndsWith(\"Key\")) = 1\nand Model.Relationships.Count(ToTable = outerIt) = 1",
"FixExpression": null,
"CompatibilityLevel": 1200
}
I'm not sure if this is META or PERF.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.