public static bool IsAtOrAboveGranularity(DimensionAttribute attribute, MeasureGroupDimension mgDim) { if (mgDim is RegularMeasureGroupDimension) { MeasureGroupAttribute granularity = GetGranularityAttribute((RegularMeasureGroupDimension)mgDim); if (granularity.AttributeID == attribute.ID) { return(true); } return(IsParentOf(attribute, granularity.Attribute)); } else if (mgDim is ManyToManyMeasureGroupDimension) { //this depends on the granularity of the m2m dimension as it appears on the intermediate measure group ManyToManyMeasureGroupDimension m2mDim = (ManyToManyMeasureGroupDimension)mgDim; return(IsAtOrAboveGranularity(attribute, m2mDim.MeasureGroup.Dimensions.Find(mgDim.CubeDimensionID))); } else { return(true); } }
/// <summary> /// Add reference dim usage /// </summary> /// <param name="measureGroup"></param> /// <param name="referenceDimID"></param> /// <param name="referenceDimAttrID"></param> /// <param name="interDimID"></param> /// <param name="interDimAttrID"></param> internal static void ADD_DIM_USAGE_REFERENCE_RELATIONSHIP( MeasureGroup measureGroup, String referenceDimID, String referenceDimAttrID, String interDimID, String interDimAttrID) { MeasureGroupDimension regDim = measureGroup.Dimensions.Find(referenceDimID); if (regDim != null) { measureGroup.Dimensions.Remove(regDim); } ReferenceMeasureGroupDimension regMgDim = new ReferenceMeasureGroupDimension(); regMgDim.CubeDimensionID = referenceDimID; regMgDim.IntermediateCubeDimensionID = interDimID; MeasureGroupAttribute mgAttr = regMgDim.Attributes.Add(referenceDimAttrID); mgAttr.Type = MeasureGroupAttributeType.Granularity; regMgDim.IntermediateGranularityAttributeID = interDimAttrID; regMgDim.Materialization = ReferenceDimensionMaterialization.Regular; measureGroup.Dimensions.Add(regMgDim); }
/// <summary> /// Recursive function. Adds nodes to the tree view control. /// Adds nodes accourding to attribute relationships /// </summary> private void AddTreeViewNodeChildren(TreeNode node, CubeAttribute cubeDimAttr , MeasureGroupDimension mgDim) { bool bIsAtOrAboveGranularity = ValidateAggs.IsAtOrAboveGranularity(cubeDimAttr.Attribute, mgDim); if (!bIsAtOrAboveGranularity) { node.ForeColor = belowGranularityColor; } else if (mgDim is ReferenceMeasureGroupDimension) { ReferenceMeasureGroupDimension refDim = (ReferenceMeasureGroupDimension)mgDim; if (refDim.Materialization == ReferenceDimensionMaterialization.Indirect) { node.ForeColor = nonMaterializedColor; } } else if (cubeDimAttr.Attribute.Usage == AttributeUsage.Parent) { node.ForeColor = parentChildAttributeColor; } foreach (AttributeRelationship attRel in cubeDimAttr.Attribute.AttributeRelationships) { CubeAttribute childAttr = cubeDimAttr.Parent.Attributes.Find(attRel.AttributeID); if (childAttr == null) break; TreeNode childNode = node.Nodes.Add(childAttr.AttributeID, childAttr.Attribute.Name); if (!childAttr.AttributeHierarchyEnabled) { childNode.NodeFont = new Font(treeViewAggregation.Font, FontStyle.Italic); childNode.ForeColor = Color.Gray; } childNode.Tag = attRel; AddTreeViewNodeChildren( childNode, childAttr,mgDim); } }
private static ColumnBinding GetReferenceDimensionIntermediateAttributeColumn(MeasureGroupDimension mgdim) { if (mgdim is ReferenceMeasureGroupDimension) { ReferenceMeasureGroupDimension refmgdim = (ReferenceMeasureGroupDimension)mgdim; if (refmgdim.IntermediateGranularityAttribute.Attribute.KeyColumns.Count != 1) { throw new Exception("Reference dimension " + refmgdim.CubeDimension.Name + " had intermediate attribute with a composite key and this isn't supported by CreatePartitions."); } return GetColumnBindingForDataItem(refmgdim.IntermediateGranularityAttribute.Attribute.KeyColumns[0]); } return null; }
internal static MeasureGroupAttribute GetGranularityAttribute(MeasureGroupDimension mgdim) { if (mgdim is ReferenceMeasureGroupDimension) { ReferenceMeasureGroupDimension refmgdim = (ReferenceMeasureGroupDimension)mgdim; foreach (MeasureGroupAttribute a in ((RegularMeasureGroupDimension)refmgdim.Parent.Dimensions[refmgdim.IntermediateCubeDimensionID]).Attributes) { if (a.Type == MeasureGroupAttributeType.Granularity) return a; } throw new Exception("Granularity attribute not found in reference measure group dimension " + mgdim.CubeDimension.Name); } else if (mgdim is RegularMeasureGroupDimension) { foreach (MeasureGroupAttribute a in ((RegularMeasureGroupDimension)mgdim).Attributes) { if (a.Type == MeasureGroupAttributeType.Granularity) return a; } throw new Exception("Granularity attribute not found in measure group dimension " + mgdim.CubeDimension.Name); } else { throw new Exception("Only measure group dimensions which are regular or reference are supported. " + mgdim.CubeDimension.Name + " is type " + mgdim.GetType().Name); } }
public static bool IsAtOrAboveGranularity(DimensionAttribute attribute, MeasureGroupDimension mgDim) { if (mgDim is RegularMeasureGroupDimension) { MeasureGroupAttribute granularity = GetGranularityAttribute((RegularMeasureGroupDimension)mgDim); if (granularity.AttributeID == attribute.ID) return true; return IsParentOf(attribute, granularity.Attribute); } else if (mgDim is ManyToManyMeasureGroupDimension) { //this depends on the granularity of the m2m dimension as it appears on the intermediate measure group ManyToManyMeasureGroupDimension m2mDim = (ManyToManyMeasureGroupDimension)mgDim; return IsAtOrAboveGranularity(attribute, m2mDim.MeasureGroup.Dimensions.Find(mgDim.CubeDimensionID)); } else { return true; } }
private static List <AggValidationWarning> CheckAggDesign(AggregationDesign aggDesign, string sCorrectAggregationDesignName, string sReportTitle) { List <AggValidationWarning> masterWarnings = new List <AggValidationWarning>(); //check for m2m agg problems foreach (Aggregation agg in aggDesign.Aggregations) { foreach (AggregationDimension aggDim in agg.Dimensions) { if (aggDim.Attributes.Count > 0 && aggDim.MeasureGroupDimension is ManyToManyMeasureGroupDimension) { ManyToManyMeasureGroupDimension m2mDim = (ManyToManyMeasureGroupDimension)aggDim.MeasureGroupDimension; MeasureGroup intermediateMG = m2mDim.MeasureGroup; List <MeasureGroupAttribute> missing = new List <MeasureGroupAttribute>(); foreach (MeasureGroupDimension commonDim in intermediateMG.Dimensions) { RegularMeasureGroupDimension regCommonDim = commonDim as RegularMeasureGroupDimension; if (commonDim.CubeDimensionID != aggDim.CubeDimensionID || regCommonDim == null) { if (!aggDim.ParentMeasureGroup.Dimensions.Contains(commonDim.CubeDimensionID)) { continue; //this isn't a shared dimension } MeasureGroupDimension dataMeasureGroupDim = aggDim.ParentMeasureGroup.Dimensions[commonDim.CubeDimensionID]; if (dataMeasureGroupDim is ManyToManyMeasureGroupDimension) { continue; //this shared dimension is m2m on the data measure group so don't include it } //this is a common dimension and the granularity attribute on the intermediate measure group needs to be in the agg bool bFoundGranularityAgg = false; MeasureGroupAttribute mga = GetGranularityAttribute(regCommonDim); AggregationDimension aggCommonDim = agg.Dimensions.Find(commonDim.CubeDimensionID); if (aggCommonDim != null) { if (aggCommonDim.Attributes.Find(mga.AttributeID) != null) { bFoundGranularityAgg = true; } } if (!bFoundGranularityAgg && mga != null) { missing.Add(mga); } } } string sWarning = "This aggregation contains many-to-many dimension [" + m2mDim.CubeDimension.Name + "]. It will not be used unless it also contains "; for (int i = 0; i < missing.Count; i++) { MeasureGroupAttribute mga = missing[i]; if (i > 0) { sWarning += " and "; } sWarning += "[" + mga.Parent.CubeDimension.Name + "].[" + mga.Attribute.Name + "]"; } if (missing.Count == 0) { sWarning = ""; } else { sWarning += ". "; } sWarning += "The many-to-many dimension [" + m2mDim.CubeDimension.Name + "] itself should not be included in the aggregation to workaround a bug."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } //check for non-materialized reference dimensions foreach (Aggregation agg in aggDesign.Aggregations) { foreach (AggregationDimension aggDim in agg.Dimensions) { if (aggDim.Attributes.Count > 0 && aggDim.MeasureGroupDimension is ReferenceMeasureGroupDimension) { ReferenceMeasureGroupDimension refDim = (ReferenceMeasureGroupDimension)aggDim.MeasureGroupDimension; if (refDim.Materialization == ReferenceDimensionMaterialization.Indirect) { string sWarning = "This aggregation contains a non-materialized reference dimension [" + refDim.CubeDimension.Name + "] which is not supported."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } //check whether all measures are semi-additive bool bAllMeasuresAreSemiAdditive = true; foreach (Measure m in aggDesign.Parent.Measures) { if (m.AggregateFunction == AggregationFunction.Count || m.AggregateFunction == AggregationFunction.DistinctCount || m.AggregateFunction == AggregationFunction.Sum || m.AggregateFunction == AggregationFunction.Min || m.AggregateFunction == AggregationFunction.Max || m.AggregateFunction == AggregationFunction.None) { bAllMeasuresAreSemiAdditive = false; break; } else if (m.AggregateFunction == AggregationFunction.ByAccount) { //if it's a ByAccount measure, we need to check the list of AggregationFunctions on each account foreach (Account acct in aggDesign.ParentDatabase.Accounts) { if (acct.AggregationFunction == AggregationFunction.Sum) //Sum is the only additive AggregationFunction allowed in account intelligence { bAllMeasuresAreSemiAdditive = false; break; } } } } //if all measures are semi-additive, find the Time dimension the semi-additive behavior operates on (which we think is the first Time dimension) if (bAllMeasuresAreSemiAdditive) { CubeDimension semiAdditiveDim = null; MeasureGroupDimension semiAdditiveMgDim = null; foreach (CubeDimension cd in aggDesign.ParentCube.Dimensions) { MeasureGroupDimension mgd = aggDesign.Parent.Dimensions.Find(cd.ID); if (mgd != null && mgd.Dimension.Type == DimensionType.Time) { semiAdditiveDim = mgd.CubeDimension; semiAdditiveMgDim = mgd; break; } } if (semiAdditiveDim == null || semiAdditiveMgDim == null || !(semiAdditiveMgDim is RegularMeasureGroupDimension)) { //TODO: should we warn about this? } else { foreach (Aggregation agg in aggDesign.Aggregations) { AggregationDimension semiAdditiveAggDim = agg.Dimensions.Find(semiAdditiveDim.ID); MeasureGroupAttribute granularity = GetGranularityAttribute((RegularMeasureGroupDimension)semiAdditiveMgDim); if (semiAdditiveAggDim == null || semiAdditiveAggDim.Attributes.Find(granularity.AttributeID) == null) { string sWarning = "This measure group contains only semi-additive measures. This aggregation will not be used when semi-additive measure values are retrieved because it does not include the granularity attribute of the semi-additive dimension ([" + semiAdditiveDim.Name + "].[" + granularity.Attribute.Name + "]). (The Exists-with-a-measure-group function can still run off this aggregation, though.)"; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } //check for aggs on parent-child attributes foreach (Aggregation agg in aggDesign.Aggregations) { foreach (AggregationDimension aggDim in agg.Dimensions) { foreach (AggregationAttribute attr in aggDim.Attributes) { if (attr.Attribute.Usage == AttributeUsage.Parent) { string sWarning = "This aggregation contains [" + aggDim.CubeDimension.Name + "].[" + attr.Attribute.Name + "] which is a parent-child attribute. This is not allowed. The aggregation should include [" + aggDim.CubeDimension.Name + "].[" + aggDim.Dimension.KeyAttribute.Name + "] instead."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } //check for aggs on AttributeHierarchyEnabled=false attributes foreach (Aggregation agg in aggDesign.Aggregations) { foreach (AggregationDimension aggDim in agg.Dimensions) { foreach (AggregationAttribute attr in aggDim.Attributes) { if (!attr.CubeAttribute.AttributeHierarchyEnabled) { string sWarning = "This aggregation contains [" + aggDim.CubeDimension.Name + "].[" + attr.Attribute.Name + "] which is not enabled as an attribute hierarchy. This is not allowed."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } //find a list of ALTER statements that alter the DEFAULT_MEMBER property in the calc script List <string> attributesWithDefaultMemberAlteredInCalcScript = new List <string>(); System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(@"ALTER\s+CUBE\s+(CURRENTCUBE|\[?" + aggDesign.ParentCube.Name + @"\]?)\s+UPDATE\s+DIMENSION\s+(.+?)\s*\,\s*DEFAULT_MEMBER\s+", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline); foreach (MdxScript script in aggDesign.ParentCube.MdxScripts) { if (script.DefaultScript) { StringBuilder sCommands = new StringBuilder(); foreach (Command cmd in script.Commands) { sCommands.AppendLine(cmd.Text); } foreach (System.Text.RegularExpressions.Match match in regEx.Matches(sCommands.ToString())) { try { attributesWithDefaultMemberAlteredInCalcScript.Add(match.Groups[2].Captures[0].Value.ToLower()); } catch { } } break; } } //build list of cube dimension attributes that have default members, are not aggregatable, or are marked as AggregationUsage=Full foreach (MeasureGroupDimension mgDim in aggDesign.Parent.Dimensions) { if (mgDim is ManyToManyMeasureGroupDimension) { continue; //don't suggest adding any m2m dimensions } CubeDimension cd = mgDim.CubeDimension; foreach (CubeAttribute ca in cd.Attributes) { if (!ca.AttributeHierarchyEnabled) { continue; } if (!IsAtOrAboveGranularity(ca.Attribute, mgDim)) { continue; } foreach (Aggregation agg in aggDesign.Aggregations) { AggregationDimension aggDim = agg.Dimensions.Find(cd.ID); if (ca.Attribute.Usage == AttributeUsage.Parent) { if (!(mgDim is RegularMeasureGroupDimension)) { continue; } if (!IsAtOrAboveGranularity(cd.Dimension.KeyAttribute, mgDim)) { continue; } //if this is a parent-child attribute and the key isn't in the agg, then check whether the parent-child attribute has a DefaultMember or is aggregatable if (aggDim == null || aggDim.Attributes.Find(cd.Dimension.KeyAttribute.ID) == null) { string sWarning = ""; if (!string.IsNullOrEmpty(ca.Attribute.DefaultMember) || attributesWithDefaultMemberAlteredInCalcScript.Contains(((string)("[" + cd.Name + "].[" + ca.Attribute.Name + "]")).ToLower())) { sWarning += "has a DefaultMember"; } if (!ca.Attribute.IsAggregatable) { if (!string.IsNullOrEmpty(sWarning)) { sWarning += " and "; } sWarning += "is not aggregatable"; } if (!string.IsNullOrEmpty(sWarning)) { sWarning = "This aggregation should probably contain [" + cd.Name + "].[" + cd.Dimension.KeyAttribute.Name + "] because [" + cd.Name + "].[" + ca.Attribute.Name + "] is a parent-child attribute which " + sWarning + "."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } //for non-parent-child attributes... else if (aggDim == null || aggDim.Attributes.Find(ca.AttributeID) == null) { string sWarning = ""; if (!string.IsNullOrEmpty(ca.Attribute.DefaultMember) || attributesWithDefaultMemberAlteredInCalcScript.Contains(((string)("[" + cd.Name + "].[" + ca.Attribute.Name + "]")).ToLower())) { sWarning += "has a DefaultMember"; } if (!ca.Attribute.IsAggregatable) { if (!string.IsNullOrEmpty(sWarning)) { sWarning += " and "; } sWarning += "is not aggregatable"; } if (ca.AggregationUsage == AggregationUsage.Full) { if (!string.IsNullOrEmpty(sWarning)) { sWarning += " and "; } sWarning += "is marked as AggregationUsage=Full"; } if (aggDim != null && AggContainsChild(aggDim, ca.Attribute)) { continue; //if this attribute is redundant, then no need to warn about it } if (!string.IsNullOrEmpty(sWarning)) { sWarning = "This aggregation should probably contain [" + cd.Name + "].[" + ca.Attribute.Name + "] which " + sWarning + "."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } } //look for aggs with redundant attributes foreach (Aggregation agg in aggDesign.Aggregations) { bool bHasRedundancy = false; foreach (AggregationDimension aggDim in agg.Dimensions) { foreach (AggregationAttribute attr in aggDim.Attributes) { if (AggContainsParent(aggDim, attr.Attribute)) { bHasRedundancy = true; break; } } if (bHasRedundancy) { break; } } if (bHasRedundancy) { string sWarning = "This aggregation contains redundant attributes which unnecessarily bloat the size of the aggregation."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } //check for aggs on below granularity attributes foreach (Aggregation agg in aggDesign.Aggregations) { foreach (AggregationDimension aggDim in agg.Dimensions) { foreach (AggregationAttribute attr in aggDim.Attributes) { if (!IsAtOrAboveGranularity(attr.Attribute, aggDim.MeasureGroupDimension)) { string sWarning = "This aggregation contains [" + aggDim.CubeDimension.Name + "].[" + attr.Attribute.Name + "] which is below granularity. This is not allowed."; masterWarnings.Add(new AggValidationWarning(agg, sCorrectAggregationDesignName, sWarning, sReportTitle)); } } } } return(masterWarnings); }
static void PartitionInfo() { string srv_name = @"SCRBMSBDK000660"; string db_name = "FBR_FYPnL_DPRD"; string cube_name = "FYPnL Cube"; string mg_name = "USD"; //TextWriter tw = new StreamWriter("date.txt", true); Microsoft.AnalysisServices.Server srv; Microsoft.AnalysisServices.Database db; srv = new Microsoft.AnalysisServices.Server(); try { srv.Connect(srv_name); logMessageFmt("Databases on [{0}]: {1}", srv_name, srv.Databases.Count); db = srv.Databases.FindByName(db_name); Cube cube = db.Cubes.FindByName(cube_name); CubeDimension cubedim = cube.Dimensions[0]; Dimension dbdim = cubedim.Dimension; DimensionAttribute dbattr = dbdim.Attributes[0]; //var Source = dbattr.Source; System.Data.DataSet ds = dbdim.DataSourceView.Schema; string dsid = db.DataSourceViews[0].DataSourceID; DataTable dt = db.DataSourceViews[0].Schema.Tables[0]; //db.DataSources[0]. //DataTable dt = ds.Tables["SHARED_DimBrand"]; //ep = dt.ExtendedProperties. MeasureGroup mg = cube.MeasureGroups.FindByName(mg_name); MeasureGroupDimension mgd = mg.Dimensions[0]; List <MeasureGroupAttribute> alist = new List <MeasureGroupAttribute>(); if (mgd is RegularMeasureGroupDimension) { RegularMeasureGroupDimension rmgd = (RegularMeasureGroupDimension)mgd; foreach (MeasureGroupAttribute mgattr in rmgd.Attributes) { if (mgattr.Type == MeasureGroupAttributeType.Granularity) { alist.Add(mgattr); } } //MeasureGroupAttribute mgattr = rmgd.Attributes.f["Key"]; } Type t = alist[0].KeyColumns[0].Source.GetType(); Measure msr = mg.Measures[0]; foreach (Partition part in mg.Partitions) { string src; TabularBinding tb = part.Source; if (tb is QueryBinding) { src = String.Format("QUERY: {0}", ((QueryBinding)tb).QueryDefinition); } else if (tb is TableBinding) { src = String.Format("TABLE: {0}.{1}", ((TableBinding)tb).DbSchemaName, ((TableBinding)tb).DbTableName); } else if (tb is DsvTableBinding) { src = String.Format("DSV: {0}.{1}", ((DsvTableBinding)tb).DataSourceViewID, ((DsvTableBinding)tb).TableID); } else { src = String.Empty; } logMessageFmt("Partition [{0}]: {1}", part.Name, src /*part.EstimatedRows*/); //part.Process() } //Partition part = mg.Partitions[0]; //.FindByName(part_name); logMessage("Done."); Console.ReadKey(); } finally { if (srv.Connected == true) { srv.Disconnect(); } } }
// Compare if attributeA is included in AttributeB private static Boolean IsRedundantAttribute(MeasureGroup mg1, string DimId, string AttributeA, string AttributeB, Boolean CompareEstimatedCount, long OriginalEstimatedCount) { if (mg1 == null) { return(false); } long lngMembersDelta; float flDeltaRatio; float flPonderatedDeltaRatio; long lngEstimatedCountToSendRecursively; MeasureGroupDimension dimension = mg1.Dimensions.Find(DimId); if (dimension == null) { return(false); } CubeAttribute cubeattribute = dimension.CubeDimension.Attributes.Find(AttributeB); if (cubeattribute == null) { return(false); } // Check if AttributeA is included in AttributeB by // standing on AttributeB and recursively searching for AttributeA in all its child relationships foreach (AttributeRelationship attrRel in cubeattribute.Attribute.AttributeRelationships) { CubeAttribute childAttr = cubeattribute.Parent.Attributes.Find(attrRel.AttributeID); if (attrRel.AttributeID == AttributeA) { // if CompareEstimatedCount is turn off, attribute is definitely included if (!CompareEstimatedCount) { return(true); } else { // Else calculate the delta between Estimated Counts if (OriginalEstimatedCount > 0) { lngMembersDelta = (OriginalEstimatedCount - childAttr.Attribute.EstimatedCount); } else { lngMembersDelta = (cubeattribute.Attribute.EstimatedCount - childAttr.Attribute.EstimatedCount); } // Calculate the ratio between the delta and the child estimated count. flDeltaRatio = (float)lngMembersDelta / (float)childAttr.Attribute.EstimatedCount; // Ponderate delta ratio by multiplying it by intMembersDelta flPonderatedDeltaRatio = flDeltaRatio * (float)lngMembersDelta; // Testings on different scenarios demostrated that if flPonderatedDeltaRatio > 1000 both attributes have much different cardinality. if (flPonderatedDeltaRatio < 1000) { // if AttributeA is included in AttributeB and besides their cardinality are similar // then A is definitely included in B. return(true); } } } if (childAttr.Attribute.AttributeRelationships.Count > 0) { // If in first iteration, OriginalEstimatedCount is null and base Estimated Count es get from AttributeB // if second or later iteration, it pushes the OriginalEstimatedCount if (OriginalEstimatedCount == -1) { lngEstimatedCountToSendRecursively = cubeattribute.Attribute.EstimatedCount; } else { lngEstimatedCountToSendRecursively = OriginalEstimatedCount; } if (IsRedundantAttribute(mg1, DimId, AttributeA, childAttr.AttributeID, CompareEstimatedCount, lngEstimatedCountToSendRecursively)) { return(true); } } } return(false); }