public static List <DimensionUsage> GetDimensionUsage(Cube c)
        {
            List <CubeDimension> listCubeDimensions = new List <CubeDimension>();

            foreach (CubeDimension cd in c.Dimensions)
            {
                listCubeDimensions.Add(cd);
            }

            List <DimensionUsage> dimUsage = new List <DimensionUsage>();

            foreach (MeasureGroup mg in c.MeasureGroups)
            {
                System.Diagnostics.Trace.Write("mg " + mg.Name);
                foreach (MeasureGroupDimension mgdim in mg.Dimensions)
                {
                    System.Diagnostics.Trace.Write(",mgdim " + mgdim.Dimension.Name);
                    if (mgdim is ReferenceMeasureGroupDimension)
                    {
                        ReferenceMeasureGroupDimension refMgDim = (ReferenceMeasureGroupDimension)mgdim;
                        getReferencedMeasureGroupAttributeUsage(dimUsage, mg, refMgDim);
                    }
                    else if (mgdim is DegenerateMeasureGroupDimension)
                    {
                        DegenerateMeasureGroupDimension degMgDim = (DegenerateMeasureGroupDimension)mgdim;
                        getFactMeasureGroupAttributeUsage(dimUsage, mg, degMgDim);
                    }
                    else if (mgdim is ManyToManyMeasureGroupDimension)
                    {
                        ManyToManyMeasureGroupDimension m2mMgDim = (ManyToManyMeasureGroupDimension)mgdim;
                        getManyToManyMeasureGroupAttributeUsage(dimUsage, mg, m2mMgDim);
                    }
                    else if (mgdim is DataMiningMeasureGroupDimension)
                    {
                        DataMiningMeasureGroupDimension dmMgDim = (DataMiningMeasureGroupDimension)mgdim;
                        getDataMiningMeasureGroupAttributeUsage(dimUsage, mg, dmMgDim);
                    }
                    else if (mgdim is RegularMeasureGroupDimension)
                    {
                        RegularMeasureGroupDimension regMDdim = (RegularMeasureGroupDimension)mgdim;
                        getRegularMeasureGroupAttributeUsage(dimUsage, mg, regMDdim);
                    }
                    if (listCubeDimensions.Contains(mgdim.CubeDimension))
                    {
                        listCubeDimensions.Remove(mgdim.CubeDimension);
                    }
                }
            }

            //add any cube dimensions which aren't related to any measure groups
            foreach (CubeDimension cd in listCubeDimensions)
            {
                DimensionUsage du = new DimensionUsage(string.Empty, null, cd, cd.Dimension);
                dimUsage.Add(du);
            }

            return(dimUsage);
        }
示例#2
0
        /// <summary>
        /// Add many to many dim_usage
        /// </summary>
        /// <param name="measureGroup"></param>
        /// <param name="internalMGID"></param>
        /// <param name="DimID"></param>
        internal static void ADD_DIM_USAGE_MANY_RELATIONSHIP(
            MeasureGroup measureGroup,
            String internalMGID,
            String DimID)
        {
            ManyToManyMeasureGroupDimension manytomanyMgDim = new ManyToManyMeasureGroupDimension();

            manytomanyMgDim.CubeDimensionID = DimID;
            manytomanyMgDim.MeasureGroupID  = internalMGID;
            measureGroup.Dimensions.Add(manytomanyMgDim);
        }
 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);
     }
 }
        /*
         * Many    Col1 - Intermediate Measure Group Name
         *
         */
        private static void getManyToManyMeasureGroupAttributeUsage(List <DimensionUsage> dimUsage, MeasureGroup mg, ManyToManyMeasureGroupDimension m2mMDdim)
        {
            DimensionUsage usage = new DimensionUsage("Many to Many", mg, m2mMDdim.CubeDimension, m2mMDdim.Dimension);

            usage.Column1Name  = "Intermediate Measure Group";
            usage.Column1Value = m2mMDdim.MeasureGroup.Name;
            dimUsage.Add(usage);
        }
        public List <M2MMatrixCompressionStat> BuildQueries(Cube cube)
        {
            List <M2MMatrixCompressionStat> listStats = new List <M2MMatrixCompressionStat>();

            foreach (MeasureGroup mg in cube.MeasureGroups)
            {
                if (mg.IsLinked)
                {
                    continue;
                }
                Dictionary <MeasureGroup, List <ManyToManyMeasureGroupDimension> > dictM2M = new Dictionary <MeasureGroup, List <ManyToManyMeasureGroupDimension> >();
                foreach (MeasureGroupDimension mgd in mg.Dimensions)
                {
                    if (mgd is ManyToManyMeasureGroupDimension)
                    {
                        ManyToManyMeasureGroupDimension m2mmgd = (ManyToManyMeasureGroupDimension)mgd;
                        if (!dictM2M.ContainsKey(m2mmgd.MeasureGroup))
                        {
                            dictM2M.Add(m2mmgd.MeasureGroup, new List <ManyToManyMeasureGroupDimension>());
                        }
                        dictM2M[m2mmgd.MeasureGroup].Add(m2mmgd);
                    }
                }
                if (dictM2M.Count > 0)
                {
                    //there are m2m dimensions used by this data measure group
                    foreach (MeasureGroup intermediateMG in dictM2M.Keys)
                    {
                        if (intermediateMG.IsLinked)
                        {
                            continue;
                        }
                        try
                        {
                            List <CubeAttribute> commonDimensions = new List <CubeAttribute>();
                            foreach (CubeDimension cd in cube.Dimensions)
                            {
                                if (mg.Dimensions.Contains(cd.ID) && intermediateMG.Dimensions.Contains(cd.ID))
                                {
                                    if (mg.Dimensions[cd.ID] is RegularMeasureGroupDimension &&
                                        intermediateMG.Dimensions[cd.ID] is RegularMeasureGroupDimension)
                                    {
                                        //it's a common dimension
                                        RegularMeasureGroupDimension rmgdData         = (RegularMeasureGroupDimension)mg.Dimensions[cd.ID];
                                        MeasureGroupAttribute        mgaData          = GetGranularityAttribute(rmgdData);
                                        RegularMeasureGroupDimension rmgdIntermediate = (RegularMeasureGroupDimension)intermediateMG.Dimensions[cd.ID];
                                        MeasureGroupAttribute        mgaIntermediate  = GetGranularityAttribute(rmgdIntermediate);
                                        CubeAttribute ca = mgaData.CubeAttribute;
                                        if (mgaData.AttributeID != mgaIntermediate.AttributeID)
                                        {
                                            if (IsParentOf(mgaIntermediate.Attribute, mgaData.Attribute))
                                            {
                                                ca = mgaIntermediate.CubeAttribute;
                                            }
                                        }
                                        commonDimensions.Add(ca);
                                    }
                                }
                            }

                            //fine while we're just doing this for SQL server
                            MeasureGroupHealthCheckPlugin.sq = "[";
                            MeasureGroupHealthCheckPlugin.fq = "]";

                            DsvTableBinding oTblBinding = new DsvTableBinding(intermediateMG.Parent.DataSourceView.ID, MeasureGroupHealthCheckPlugin.GetTableIdForDataItem(intermediateMG.Measures[0].Source));
                            string          sFactQuery  = "(" + MeasureGroupHealthCheckPlugin.GetQueryDefinition(intermediateMG.ParentDatabase, intermediateMG, oTblBinding, null) + ")";

                            List <string> listCommonDimensionsSeen = new List <string>();
                            string        sCommonDimensions        = "";
                            string        sCommonDimensionsJoin    = "";
                            foreach (CubeAttribute ca in commonDimensions)
                            {
                                RegularMeasureGroupDimension rmgd = (RegularMeasureGroupDimension)intermediateMG.Dimensions[ca.Parent.ID];
                                if (rmgd is ReferenceMeasureGroupDimension)
                                {
                                    if (mg.Dimensions.Contains(((ReferenceMeasureGroupDimension)rmgd).IntermediateCubeDimensionID) &&
                                        mg.Dimensions[((ReferenceMeasureGroupDimension)rmgd).IntermediateCubeDimensionID] is RegularMeasureGroupDimension)
                                    {
                                        continue; //skip reference dimensions in the intermediate measure group because it won't change the cardinality
                                    }
                                    else
                                    {
                                        throw new Exception(rmgd.CubeDimension.Name + " dimension in intermediate measure group " + intermediateMG.Name + " is not supported by BIDS Helper M2M Matrix Compression");
                                    }
                                }

                                MeasureGroupAttribute mga = rmgd.Attributes[ca.AttributeID];
                                foreach (DataItem di in mga.KeyColumns)
                                {
                                    if (di.Source is ColumnBinding)
                                    {
                                        if (!listCommonDimensionsSeen.Contains("[" + ((ColumnBinding)di.Source).ColumnID + "]")) //if this column is already mentioned, then don't mention it again
                                        {
                                            listCommonDimensionsSeen.Add("[" + ((ColumnBinding)di.Source).ColumnID + "]");
                                            if (sCommonDimensionsJoin.Length == 0)
                                            {
                                                sCommonDimensionsJoin += "WHERE ";
                                            }
                                            else
                                            {
                                                sCommonDimensionsJoin += "\r\nAND ";
                                                sCommonDimensions     += ", ";
                                            }
                                            sCommonDimensionsJoin += "f.[" + ((ColumnBinding)di.Source).ColumnID + "] = s.[" + ((ColumnBinding)di.Source).ColumnID + "]";
                                            sCommonDimensions     += "[" + ((ColumnBinding)di.Source).ColumnID + "]";
                                        }
                                    }
                                }
                            }

                            List <string> listM2MDimensionsSeen = new List <string>();
                            string        sM2MDimensions        = "";
                            string        sM2MDimensionsOrderBy = "";
                            foreach (ManyToManyMeasureGroupDimension m2mmgd in dictM2M[intermediateMG])
                            {
                                if (intermediateMG.Dimensions[m2mmgd.CubeDimensionID] is RegularMeasureGroupDimension)
                                {
                                    RegularMeasureGroupDimension rmgd = (RegularMeasureGroupDimension)intermediateMG.Dimensions[m2mmgd.CubeDimensionID];
                                    if (rmgd is ReferenceMeasureGroupDimension)
                                    {
                                        continue;                                         //won't change
                                    }
                                    if (rmgd is ReferenceMeasureGroupDimension)
                                    {
                                        if (mg.Dimensions.Contains(((ReferenceMeasureGroupDimension)rmgd).IntermediateCubeDimensionID) &&
                                            mg.Dimensions[((ReferenceMeasureGroupDimension)rmgd).IntermediateCubeDimensionID] is ManyToManyMeasureGroupDimension)
                                        {
                                            continue; //skip reference dimensions in the intermediate measure group because it won't change the cardinality
                                        }
                                        else
                                        {
                                            throw new Exception(rmgd.CubeDimension.Name + " dimension in intermediate measure group " + intermediateMG.Name + " is not supported by BIDS Helper M2M Matrix Compression");
                                        }
                                    }

                                    MeasureGroupAttribute mga = GetGranularityAttribute(rmgd);
                                    foreach (DataItem di in mga.KeyColumns)
                                    {
                                        if (di.Source is ColumnBinding)
                                        {
                                            if (!listM2MDimensionsSeen.Contains("[" + ((ColumnBinding)di.Source).ColumnID + "]")) //if this column is already mentioned, then don't mention it again
                                            {
                                                listM2MDimensionsSeen.Add("[" + ((ColumnBinding)di.Source).ColumnID + "]");
                                                if (sM2MDimensions.Length > 0)
                                                {
                                                    sM2MDimensions        += " + '|' + ";
                                                    sM2MDimensionsOrderBy += ", ";
                                                }
                                                sM2MDimensions        += "isnull(cast([" + ((ColumnBinding)di.Source).ColumnID + "] as nvarchar(max)),'')";
                                                sM2MDimensionsOrderBy += "[" + ((ColumnBinding)di.Source).ColumnID + "]";
                                            }
                                        }
                                    }
                                }
                            }

                            string sSQL = @"
SELECT (SELECT COUNT(*) FROM " + sFactQuery + @" x) OriginalRecordCount
, COUNT(MatrixKey) MatrixDimensionRecordCount
, SUM(cast(KeyCount AS FLOAT)) CompressedRecordCount
FROM (
 SELECT DISTINCT COUNT(*) KeyCount
 , MatrixKey = (
  SELECT " + sM2MDimensions + @" AS [data()] 
  FROM " + sFactQuery + @" f
  " + sCommonDimensionsJoin + @"
  ORDER BY " + sM2MDimensionsOrderBy + @"
  FOR XML PATH ('')
 )
 FROM " + sFactQuery + @" s 
 GROUP BY " + sCommonDimensions + @"
) SUBQ
";
                            M2MMatrixCompressionStat stat = new M2MMatrixCompressionStat();
                            stat.IntermediateMeasureGroup = intermediateMG;
                            stat.DataMeasureGroup         = mg;
                            stat.SQL = sSQL;
                            listStats.Add(stat);
                        }
                        catch (Exception ex)
                        {
                            M2MMatrixCompressionStat stat = new M2MMatrixCompressionStat();
                            stat.IntermediateMeasureGroup = intermediateMG;
                            stat.DataMeasureGroup         = mg;
                            stat.Error = ex.Message + "\r\n" + ex.StackTrace;
                            listStats.Add(stat);
                        }
                    }
                }
            }

            return(listStats);
        }
 /*
  * Many    Col1 - Intermediate Measure Group Name
  * 
  */
 private static void getManyToManyMeasureGroupAttributeUsage(List<DimensionUsage> dimUsage, MeasureGroup mg, ManyToManyMeasureGroupDimension m2mMDdim)
 {
     DimensionUsage usage = new DimensionUsage("Many to Many", mg, m2mMDdim.CubeDimension, m2mMDdim.Dimension);
     usage.Column1Name = "Intermediate Measure Group";
     usage.Column1Value = m2mMDdim.MeasureGroup.Name;
     dimUsage.Add(usage);
 }
        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);
        }