Skip to content

部署多维数据集项目

🏷️ Visual Studio

开发环境

本文中示例代码的开发环境如下:

IDE:Visual Studio 2015
SqlServer:Microsoft SQL Server 2014

如果 VS 2015 打不开 BI 项目可以参考 这篇文章

发布多维数据集

在 VS 中右键需要发布的多维数据集项目,选择 部署

如需修改部署设置,右键项目选择 属性 。在 配置 下拉框中可以选择部署的配置,点击 配置管理器 按钮可以新增/修改配置。
在左侧的 配置属性 - 部署 页面可以设置部署的 目标服务器数据库。(目标服务器需要安装 SQL Server Analysis Services (MSSQLSERVER) 服务)

这里也遇到了些坑,主要是由于测试环境的数据好多都是错误的,导致了多维数据集中维度中的主键冲突(维度设置的主键冲突是报错),从而导致部署失败。(虽然失败了,但是多维数据集的结构其实已经部署上去了)
由于错误数据太多我也没法处理,直接修改了维度中主键冲突(KeyDuplicate)的设置为 IgnoreError 然后再部署。
设置方法:打开维度的设计器,右键 属性 区域,选择属性。然后在打开的属性小窗口中展开 ErrorConfiguration 属性就可以看到 KeyDuplicate 属性了,这里还可以设置 CalculationErrorKeyNotFound 等属性。

MSOLAP

由于项目中使用的 AdomdConnectionproviderMSOLAP 。这需要在 IIS 中添加 msmdpump.dll 文件的访问。
(这个文件应该是 SqlServer 提供的,我这个是公司运维给我的。)

IIS 通过 添加应用程序 的方式添加 olap 子目录。

访问时若出现 404.2 错误可以参考错误页面上的步骤设置。

HTTP 错误 404.2 - Not Found
由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面。

设置 “ISAPI 和 CGI 限制” 的步骤:

  1. 打开 IIS 管理器并定位到服务器级别。

  2. 在“功能”视图中,双击“ISAPI 和 CGI 限制”以确认 Web 服务扩展被设置为“允许”。

  3. 如果该扩展不在列表中,请在“操作”窗格中单击“添加”。

  4. 在“描述”框中,键入该限制的简要说明。

  5. (可选) 选中“允许执行扩展路径”以使限制可以自动运行。如果不选中此选项,则限制状态将为“不允许”,这是默认状态。您可以在以后选中此选项并单击“操作”窗格中的“允许”来允许该限制。

  6. 单击“确定”。

注意

在这里我踩了个坑,忽略了上面的第一步,导致我在网站的设置页面找了半天,还在网上查了半天。
“ISAPI 和 CGI 限制” 这个设置是在 IIS 左侧栏根目录的设置页面上的。

配置成功后访问通过浏览器直接访问 http://localhost/olap/msmdpump.dll 可以看到如下界面:

查询多维数据集

写了一个简单的控制台应用程序,查询多维数据集中的数据。

安装 AdomdClient 相关包

Newtonsoft.Json 包是示例中为了方便打印使用的,可以根据项目需要选择性安装。

powershell
Install-Package Microsoft.AnalysisServices.AdomdClient.retail.amd64 -Version 18.2.3
Install-Package Newtonsoft.Json -Version 12.0.3

C# 代码示例

项目类型:控制台应用程序
目标框架:.NET Framework 4.5.2

Program.cs

csharp
using Microsoft.AnalysisServices.AdomdClient;
using Newtonsoft.Json;
using System;
using System.Data;

namespace AdomdSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var connectionString = "provider=MSOLAP; Integrated Security =SSPI; Data Source =http://localhost/olap/msmdpump.dll; Catalog = Octopus Cubes;";
            var command = @"..."; // 多维数据集的查询语句

            using (var connection = new AdomdConnection(connectionString))
            {
                connection.Open();
                var adoMD = connection.CreateCommand();
                adoMD.CommandText = command;
                CellSet cs = adoMD.ExecuteCellSet();
                DataTable dt = cs.ToDataTable();
                Console.WriteLine(JsonConvert.SerializeObject(dt));
                Console.ReadLine();
            }
        }
    }
}

AdomdExtensions.cs

提供了一个扩展方法,将多维数据集的查询结果 CellSet 转换为 DataTable

csharp
using Microsoft.AnalysisServices.AdomdClient;
using System.Data;

namespace AdomdSample
{
    static class AdomdExtensions
    {
        /// <summary>
        /// 将 CellSet 转化成 DataTable(包括所有维度)
        /// </summary>
        /// <param name="cs">CellSet</param>
        /// <returns></returns>
        public static DataTable ToDataTable(this CellSet cs)
        {
            DataTable dt = new DataTable();
            dt.TableName = "ResultTable";
            DataColumn dc = null;
            DataRow dr = null;

            //生成数据列对象
            //多个维度转化成列
            for (int col = 0; col < cs.Axes[1].Set.Hierarchies.Count; col++)
            {
                dc = new DataColumn();
                //下面的代码会报错:"The connection is not open.”获取层次结构的维度名时需要连接 Cube 才可以!
                //dt.Columns.Add(new DataColumn(cs.Axes[1].Set.Hierarchies[col].ParentDimension.Name));
                dt.Columns.Add(new DataColumn("Dimension" + col.ToString()));
            }

            int index = 0;
            foreach (Position p in cs.Axes[0].Positions)
            {
                dc = new DataColumn();
                string name = "";
                foreach (Member m in p.Members)
                {
                    name += m.Caption + "-";
                }
                if (name.Length > 0)
                {
                    name = name.Substring(0, name.Length - 1);
                }
                //这里防止维度成员或度量值重名而需要容错处理
                try
                {
                    dc.ColumnName = name;
                    dt.Columns.Add(dc);
                }
                catch (System.Exception)
                {
                    dc.ColumnName = name + index.ToString();
                    dt.Columns.Add(dc);
                }
                index++;
            }

            //添加行数据
            int pos = 0;
            foreach (Position py in cs.Axes[1].Positions)
            {
                dr = dt.NewRow();

                //维度描述列数据
                int cols = 0;
                foreach (Member m in py.Members)
                {
                    dr[cols] = m.Caption;
                    cols++;
                }

                //数据列
                for (int x = 1; x <= cs.Axes[0].Positions.Count; x++)
                {
                    dr[x + cols - 1] = cs[pos++].FormattedValue;
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }
    }
}