从C#中的MDX查询/单元集中检索度量的数据类型

时间:2012-03-30 22:48:55

标签: mdx

(我正在使用C#4.0。我通过Microsoft.AnalysisServices.AdomdClient命名空间/库连接到数据立方体。)

如果我理解正确,MDX SELECT语句中只有一个轴将包含度量;其他的将基于其他方面。

我的当前任务(更大的任务是无关紧要的,我相信)给定一个MDX SELECT语句,使得第一个轴包含所述度量,我需要以编程方式确定数据类型所有与每项措施有关的细胞。

我认为,实现此目的的一种方法是使用AdomdConnection并引用CubeDef类来获取度量信息,并将其与Cellset.Set.Tuples.Members类似的东西进行匹配,但那么如何为在SELECT?

中使用“WITH”关键字进行实时测量

另一种方法是查看与给定度量关联的Cell对象的Value属性,从执行SELECT语句并在CellSet中找到非null Cell,但我们不能保证找到非null值,所以这不是防止失败的。

我查看了VS调试器中的CellSet,但没有找到任何提供此信息的属性。

解决方案: 事实证明,度量可能有多种数据类型。至少对于使用WITH子句定义的度量,如下所示:

  

WITH MEMBER [Measures]。[Dud]如[测量]的情况。[原创]> 500那么'A'结束0结束

因此,数据类型信息存储在每个单元格中,而不是存储在某种度量元数据中。随后,学习模式的唯一方法是假设它们都是相同的类型,然后遍历度量维度,直到找到非空单元格,然后学习它的类型。

1 个答案:

答案 0 :(得分:4)

我们实际上是基于ADOMD数据提供程序编写了自己的.NET Framework数据提供程序。我们希望在今年晚些时候开源,但下面是我如何做你想做的事情的摘录。

我使用了AdomdCommand对象的ExecuteXmlReader。返回的xml将包含单元格的一部分。

AdomdCommand command = new AdomdCommand();
command.Connection = new AdomdConnection(connectionString);
command.Connection.Open();
command.CommandText = query;
var doc = XDcoument.Load(command.ExecuteXmlReader());

var cellData = from cell in doc.Root.Elements(_namespace + "CellData").Elements(_namespace + "Cell")
                       select new
                       {
                           Ordinal = (int)cell.Attribute("CellOrdinal"),
                           FormattedValue = cell.Elements(_namespace + "FmtValue").Any() ? cell.Element(_namespace + "FmtValue").Value : cell.Element(_namespace + "Value").Value,
                           Value = cell.Element(_namespace + "Value").Value,
                           Type = (string)cell.Element(_namespace + "Value").Attribute(_xsiNs + "type"),

                       };

每个单元格都有一个数据类型。对于给定的列,我们需要该列中的所有单元格。

var x = cells.Where(c => ((c.Ordinal + 1) % columnCount) == columnPosition).Select(t => t.Type).Distinct();
 if (x.Count() > 1)
        {
            // if a non number comes back, the type is null, so non numbers are null
            // on counts of greater than 1 and no nulls, we have multiple number types, make them all double to accommodate the differences
            if ( !x.Contains(null) )
            {
                // mix of numbers not doubles, default to int
                if (!x.Contains("xsd:double"))
                {
                    type = typeof(int);
                }
                else
                {
                    type = typeof(double);
                }
            }
            else
            {
                type = typeof(string);
            }
        }
        else
        {
            // entire column maybe null, default to string, otherwise check
            if (x.Count() == 1)
            {
                type = ConvertXmlTypeToType(x.First());
            }               
        }

最后,我有将Xml类型转换为.NET类型

的函数
private Type ConvertXmlTypeToType(string type)
    {
        Type t = typeof(string);

        switch (type)
        {
            case "xsd:int":
                t = typeof(int);
                break;
            case "xsd:double":
                t = typeof(double);
                break;
            case "xsd:long":
                t = typeof(long);
                break;
            case "xsd:short":
                t = typeof(short);
                break;
            case "xsd:integer":
                t = typeof(int);
                break;
            case "xsd:decimal":
                t = typeof(decimal);
                break;
            case "xsd:float":
                t = typeof(float);
                break;
            default:
                t = typeof(string);
                break;
        }

        return t;
    }