如何:为 PerformancePoint Services 筛选器创建数据提供程序

上次修改时间: 2011年8月30日

在 Microsoft SharePoint Server 2010 中的 PerformancePoint Services 中,数据提供程序从筛选器的基础数据源中检索数据并定义如何使用这些数据。最重要的是,数据提供程序指定要在筛选控件中公开的数据值和可用作筛选器起始点的数据。数据提供程序还会存储用户从筛选控件中选择的值,这些值随后将发送给筛选器使用方。数据提供程序使用两个 DataTable 对象来组织和存储数据。有关详细信息,请参阅PerformancePoint Services 筛选器

适用范围: SharePoint Server 2010

本主题中的过程和示例基于自定义对象示例中的 SampleFilterDataProvider 类。该编辑器是一类瘦 Web 应用程序,用户可使用此应用程序修改报告的名称和说明。本主题中的"示例"一节提供了该类的完整代码。

备注

建议您将示例数据提供程序用作模板。该示例说明如何调用 PerformancePoint Services API 中的对象,并演示针对 PerformancePoint Services 开发的最佳实践。

通过执行两个基本过程来创建数据提供程序,如下所示:

  • 创建和配置提供程序类

  • 定义提供程序功能

若要创建自定义提供程序,请先创建提供程序类。

创建和配置提供程序类

  1. 安装 PerformancePoint Services,或将您的扩展使用的 DLL(步骤 3 中已列出)复制到计算机上。有关详细信息,请参阅 开发方案中使用的 PerformancePoint Services DLL

  2. 在 Visual Studio 中创建 C# 类库。如果已经为您的扩展创建了类库,则添加一个新的 C# 类。

  3. 添加下面的 PerformancePoint Services DLL 作为对项目的程序集引用:

    • Microsoft.PerformancePoint.Scorecards.Client.dll

    • Microsoft.PerformancePoint.Scorecards.Server.dll

    根据扩展的功能不同,可能需要其他项目引用。

  4. 在您的提供程序类中,为以下 PerformancePoint Services 命名空间添加 using 指令:

    根据扩展的功能不同,可能需要其他 using 指令。

  5. CustomParameterDataProvider 基类继承。

在创建和配置提供程序类后,必须定义提供程序的功能。

定义提供程序功能

  1. 为数据提供程序名称设置字符串标识符。此标识符必须与在注册扩展时添加到 web.config 文件的 CustomParameterDataProviders 部分中的项匹配。有关详细信息,请参阅如何:手动注册 PerformancePoint Services 扩展

  2. 替代 GetId() 方法,以返回数据提供程序的标识符。

  3. 替代 GetDisplayDataInternal 方法,以定义要存储来自基础数据源的数据值的 DataTable 对象。筛选器可使用此方法填充筛选器选择控件。显示模拟运算表必须包含以下列名:

    • Key  记录的唯一标识符。该值不能为空。出于性能和安全原因,控件只发出一个项;控件不发出其他列中的值。

    • Display  筛选器控件中显示的值。

    • ParentKey  此值用于排列树控件中的分层数据。

    • IsDefault  此值用于设置筛选器的持久性。

      提示提示

      可以添加多个列以扩展筛选器功能。

    GetDisplayDataInternal 可调用 DataSourceRegistry.GetDataSource(DataSource) 方法以按名称验证数据源类型,如下所示:

    • 它通过使用数据源的 SubTypeId 属性来引用自定义数据源类型,该属性的值与在 PerformancePoint Services web.config 文件中为数据源扩展注册的 subType 特性的值相同。

    • 它通过使用 SourceName 属性来引用本机数据源,该属性返回 DataSourceNames 类中的字段。

  4. 替代 GetMessageData 方法,以存储用户在筛选器控件中选择的内容。

    **下一步:**在创建数据提供程序和筛选器编辑器(如果需要,包括其用户界面)后,部署扩展,如如何:手动注册 PerformancePoint Services 扩展中所述。有关如何安装和配置示例筛选器扩展的说明,请参阅代码示例:自定义报表、筛选器和表格数据源对象中的"安装示例报表、筛选器和数据源对象"一节。

示例

以下代码示例演示数据提供程序如何从 Web 服务或 Excel 工作表检索值,并为筛选器的显示数据和消息数据返回 DataTable 对象。

备注

您必须先按创建和配置提供程序类中所述配置开发环境,然后才能编译此代码示例。

using System.Data;
using Microsoft.PerformancePoint.Scorecards;
using Microsoft.PerformancePoint.Scorecards.Server.Extensions;

namespace Microsoft.PerformancePoint.SDK.Samples.SampleFilter
{

    // Represents the sample filter's data provider.
    public class SampleFilterDataProvider : CustomParameterDataProvider
    {

        // This value must match the key that you register for this extension
        // in the CustomParameterDataProviders section in the web.config file.
        private const string dataProviderName = "SampleFilterDataProvider";

        // Returns a table of all possible values (rows) for the
        // filter’s beginpoints. The filter's BeginPoint property returns
        // one ParameterDefinition object.
        protected override DataTable GetDisplayDataInternal(ParameterDefinition parameterDefinition, RepositoryLocation parameterSourceLocation, object custom)
        {
            DataTable retrievedData = null;

            // Get the data source.
            DataSource parameterDataSource = SafeGetDataSource(parameterSourceLocation);
            if (null != parameterDataSource)
            {

                // Verify that the data source is the sample data source
                // or an Excel workbook, which are the types that the
                // sample supports.
                // If you modify these types of data source, you must make
                // the corresponding change in the filter's editor.
                if (parameterDataSource.SourceName == "WSTabularDataSource" || parameterDataSource.SourceName == DataSourceNames.ExcelWorkbook)
                {
                    IDataSourceProvider parameterDataSourceProvider =
                        DataSourceRegistry.GetDataSource(parameterDataSource);
                    if (null != parameterDataSourceProvider)
                    {
                        var dataSourceMetadata = parameterDataSourceProvider as IDataSourceMetadata;
                        if (null != dataSourceMetadata)
                        {

                            // Get the data and store it in the retrievedDataSet
                            // variable. The -1 parameter returns all records
                            // from the data source.
                            DataSet retrievedDataSet = dataSourceMetadata.GetPreviewDataSet(-1);

                            // Verify that the dataset contains data.  
                            if (retrievedDataSet != null &&
                                retrievedDataSet.Tables != null &&
                                retrievedDataSet.Tables.Count > 0 &&
                                retrievedDataSet.Tables[0] != null &&
                                retrievedDataSet.Tables[0].Columns != null &&
                                retrievedDataSet.Tables[0].Columns.Count > 0 &&
                                retrievedDataSet.Tables[0].Rows != null &&
                                retrievedDataSet.Tables[0].Rows.Count > 0 &&
                                retrievedDataSet.Tables[0].Columns.Contains(parameterDefinition.KeyColumn))
                            {
                                retrievedData = retrievedDataSet.Tables[0];
                            }
                        }
                    }
                }

                if (null != retrievedData)
                {
                    // Name the display data table.
                    retrievedData.TableName = "ParamData";

                    // Verify that the table has the correct structure. 
                    EnsureDataColumns(retrievedData, parameterDefinition);

                    bool firstRowSeen = false;
                    foreach (DataRow row in retrievedData.Rows)
                    {
                        // Set the ParentKeyColumn to null because the data
                        // does not have a hierarchical structure.
                        row[parameterDefinition.ParentKeyColumn] = null;

                        // Set the IsDefaultColumn column in the first row to true.
                        row[parameterDefinition.IsDefaultColumn] = !firstRowSeen;
                        if (!firstRowSeen)
                        {
                            firstRowSeen = true;        
                        }
                    }

                    // Set the column visibility.
                    SetColumnVisibility(retrievedData);
                }
            }
            
            return retrievedData;
        }

        // Adds the ShowColumn extended property to a column in the display data table
        // and sets it to true. This exposes the column in Dashboard Designer as 
        // a source value for the beginpoint. 
        private static void SetColumnVisibility(DataTable displayData)
        {
            for (int i = 0; i < displayData.Columns.Count; i++)
            {
                if (!displayData.Columns[i].ExtendedProperties.Contains("ShowColumn"))
                {
                    displayData.Columns[i].ExtendedProperties.Add("ShowColumn", true);
                }
            }
        }

        // Verify that all required columns are in the data table.
        // The data table returned by this method is expected to contain a
        // Key, ParentKey, IsDefault, Display, and an arbitrary number of
        // Value columns.
        // The specific column names (except for Value columns) are defined
        // in the filter's ParameterDefinition object, which is referenced by
        // the filter's BeginPoint property.
        private static void EnsureDataColumns(DataTable dataTable, ParameterDefinition parameterDefinition)
        {
            if (!string.IsNullOrEmpty(parameterDefinition.KeyColumn) && !dataTable.Columns.Contains(parameterDefinition.KeyColumn))
            {
                dataTable.Columns.Add(parameterDefinition.KeyColumn);
            }
            if (!string.IsNullOrEmpty(parameterDefinition.DisplayColumn) && !dataTable.Columns.Contains(parameterDefinition.DisplayColumn))
            {
                dataTable.Columns.Add(parameterDefinition.DisplayColumn);
            }
            if (!string.IsNullOrEmpty(parameterDefinition.ParentKeyColumn) && !dataTable.Columns.Contains(parameterDefinition.ParentKeyColumn))
            {
                dataTable.Columns.Add(parameterDefinition.ParentKeyColumn);
            }
            if (!string.IsNullOrEmpty(parameterDefinition.IsDefaultColumn) && !dataTable.Columns.Contains(parameterDefinition.IsDefaultColumn))
            {
                dataTable.Columns.Add(parameterDefinition.IsDefaultColumn, typeof(bool));
            }
        }

        // Returns the unique string identifier of the data provider.
        // This value must match the key that you register for this extension
        // in the CustomParameterDataProviders section in the web.config file.
        public override string GetId()
        {
            return dataProviderName;
        }

        // Returns a table of rows that match the keys in the passed
        // ParameterMessage object.
        // This method is used by controls that accept parameters, such as
        // scorecard and reports. It can also apply a Post Formula.
        public override DataTable GetMessageData(RepositoryLocation providerLocation, ParameterMessage parameterMessage, RepositoryLocation parameterSourceLocation, ParameterMapping parameterMapping, object custom)
        {   
            DataTable msgTable = null;

            // The ParameterMapping object contains information about
            // linked dashboard items.
            // The CustomData object is optionally used to store information
            // that is not stored in other properties.
            DataTable displayTable = GetDisplayDataInternal(parameterMessage, parameterSourceLocation, custom);

            if (null != displayTable)
            {
                msgTable = displayTable.Clone();
                for (int i = 0;i < parameterMessage.Values.Rows.Count; i++)
                {
                    for (int j = 0;j < displayTable.Rows.Count; j++)
                    {
                        if (!parameterMessage.Values.Rows[i][parameterMessage.KeyColumn].Equals(displayTable.Rows[j][parameterMessage.KeyColumn].ToString())) 
                            continue;

                        msgTable.ImportRow(displayTable.Rows[j]);
                        break;
                    }
                }
            }

            return msgTable;
        }
    }
}

编译代码

您必须先按创建和配置提供程序类中所述配置开发环境,然后才能编译此代码示例。

安全性

您必须使用强名称对 DLL 进行签名。此外,确保 DLL 引用的所有程序集都具有强名称。有关如何使用强名称对程序集进行签名以及如何创建公钥/私钥对的信息,请参阅How to: Create a Public/Private Key Pair

请参阅

任务

如何:为 PerformancePoint Services 筛选器创建编辑器

概念

PerformancePoint Services 筛选器

其他资源

为 PerformancePoint Services 创建自定义对象

SharePoint Server 2010 中的 PerformancePoint Services 的代码示例