65.9K
CodeProject 正在变化。 阅读更多。
Home

将 Microsoft ADOMD 单元集转换为 JSON

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.55/5 (8投票s)

2015年2月26日

CPOL

3分钟阅读

viewsIcon

14415

将 Microsoft ADOMD 单元集转换为 JSON

引言

大家好,你们好吗?我是 Sibeesh Venu。今天我遇到一个将 Microsoft ADOMD 单元集转换为 JSON 的需求。所以我想把它分享给大家。我希望你们会喜欢。

背景

过去几个月我一直在使用 Microsoft ADOMD 数据源。我还写了一些文章来描述我遇到的问题。如果您不熟悉 ADOMD,我强烈建议您阅读我之前的文章,您可能会发现这些文章在使用 ADOMD 数据源时很有用。您可以在这里找到这些文章链接。

为什么?

您可能会想,为什么我又要使用前面两篇文章中描述的方法呢?我来回答一下。我遇到了一些这些方法的问题。当您使用数据适配器或数据读取器(如第一个链接中所述 (如何将 Microsoft ADOMD 数据源转换为 JSON))时,您总是得到普通值而不是格式化值。例如,即使值包含 $ 或 %,您也总是会得到没有这些符号的值。因此,您的应用程序不会让用户识别哪个是货币,哪个是%。在我的例子中,它是 Highcharts 和 Highmaps。当用户悬停在特定区域上时,我需要在工具提示中显示度量值。

所以在这种情况下,我被迫再次使用单元集,其中有一个选项可以选择格式化值。我会在我的函数中向您展示。

使用代码

以下是执行上述操作的函数。

   private string BuildBubbleMap(CellSet cst)
        {
            try
            {               
                StringBuilder sb = new StringBuilder();
                StringWriter sw = new StringWriter(sb);
                string columnName = string.Empty;
                string fieldVal = string.Empty;              
                //check if any axes were returned else throw error.
                int axes_count = cst.Axes.Count;
                if (axes_count == 0)
                    throw new Exception("No data returned for the selection");

                //if axes count is not 2
                if (axes_count != 2)
                    throw new Exception("The code support only queries with two axes");

                //if no position on either row or column throw error
                if (!(cst.Axes[0].Positions.Count > 0) && !(cst.Axes[1].Positions.Count > 0))
                    throw new Exception("No data returned for the selection");

                int cur_row, cur_col, col_count, row_count, col_dim_count, row_dim_count;
                row_dim_count = 0;

                //Number of dimensions on the column
                col_dim_count = cst.Axes[0].Positions[0].Members.Count;

                //Number of dimensions on the row
                if (cst.Axes[1].Positions.Count > 0)
                {
                    if (cst.Axes[1].Positions[0].Members.Count > 0)
                        row_dim_count = cst.Axes[1].Positions[0].Members.Count;
                }
                //Total rows and columns
                row_count = cst.Axes[1].Positions.Count + col_dim_count;  //number of rows + rows for column headers
                col_count = cst.Axes[0].Positions.Count + row_dim_count;  //number of columns + columns for row headers

                using (JsonWriter myJson = new JsonTextWriter(sw))
                {
                    myJson.WriteStartArray();                    
                    for (cur_row = 0; cur_row < row_count-1; cur_row++)
                    {
                        myJson.WriteStartObject();                          
                        for (cur_col = 0; cur_col < col_count-1; cur_col++)
                        {                                     
                            //Looping for dimension headers
                            columnName = cst.Axes[1].Positions[cur_row].Members[cur_col].ParentLevel.ToString().Replace("{", "").Replace("}", "").Trim();
                            fieldVal = cst.Axes[1].Positions[cur_row].Members[cur_col].Caption.Replace(",", " ");
                            //If the value is null, I dont need that to be included
                            if ((columnName == null || columnName == "" || columnName.ToLower() == "undefined" || columnName.ToLower() == "null" ||
                                columnName.ToLower() == "(null)" || columnName.ToLower() == "unknown")||(fieldVal == null || fieldVal == "" ||
                                fieldVal.ToLower() == "undefined" || fieldVal.ToLower() == "null" ||
                                fieldVal.ToLower() == "(null)" || fieldVal.ToLower() == "unknown"))
                                break;
                            //Map expect the header as lat and lon, so here we are changing that.
                            if (columnName.ToLower() == "latitude")
                                columnName = "lat";
                            else if (columnName.ToLower() == "longitude")
                                columnName = "lon";                            

                            myJson.WritePropertyName(columnName);
                            myJson.WriteValue(fieldVal);                                                    
                        }
                        //Looping for measure headers
                        myJson.WritePropertyName(cst.Axes[0].Positions[0].Members[0].Caption.Replace(",", " ").Trim());
                        myJson.WriteValue(cst[cur_row].FormattedValue);
                        myJson.WriteEndObject();
                    }                   
                    myJson.WriteEndArray();
                }
                cst = null;              
                return sw.ToString();               
            }
            catch (Exception)
            {
                cst = null;
                throw;
            }
        }

您可以看到此函数需要单元集参数。在这里,我们正在查找轴(Axis0 和 Axis 1)。根据我的 ADOMD 查询,我的维度在 Axis 1 中,因此我需要从单元集中确定每个维度的标题。一旦我确定了维度,我就会使用 JSON Writer 类的 `WritePropertyName()` 方法将其写入 StringBuilder。要使用此类,您必须包含 Newtonsoft DLL,如下所示。

using Newtonsoft.Json;

完成后,我将使用 JSON writer 类的 WriteValue() 方法写入这些维度的值。

我也对度量值做了同样的处理。您可以在我的代码中看到这些实现。

最后,我在这里创建正确的 JSON 并返回它。

要使用此函数,您需要首先构建单元集。您可以按如下方式执行此操作。

                using (AdomdConnection conn = new AdomdConnection(adoMDConnection))
                {
                    conn.Open();
                    using (AdomdCommand cmd = new AdomdCommand(query, conn))
                    {
                    cmd.CommandTimeout = connectionTimeout;
                    cst = cmd.ExecuteCellSet();
                    }
                }

一旦您获得了单元集,只需将单元集传递给前面的函数,它就会返回您需要的 JSON。您可以轻松地将其绑定到任何客户端工具(例如,Highcharts 和 Highmaps)。

结论

我希望有人会发现这有用。祝您编程愉快。请提供您的宝贵建议和意见。提前感谢。

© . All rights reserved.