(我正在使用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结束
因此,数据类型信息存储在每个单元格中,而不是存储在某种度量元数据中。随后,学习模式的唯一方法是假设它们都是相同的类型,然后遍历度量维度,直到找到非空单元格,然后学习它的类型。
答案 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;
}