SharePoint で PerformancePoint Services 用の表形式のデータ ソース プロバイダーを作成する

PerformancePoint サービス のユーザー設定の表形式データ ソース拡張機能のデータ ソース プロバイダー コンポーネントを作成する方法を確認します。

PerformancePoint サービス のユーザー設定のデータ ソース プロバイダーの概要

データ ソース プロバイダーは、データ ソースに接続し、そのデータにアクセスして、クエリ結果を返します。 PerformancePoint サービス は、表形式のデータ ソース プロバイダーを使用して、Excel および Excel Services ワークシート、SharePoint リスト、Microsoft SQL Server テーブルのデータにアクセスします。 カスタム データ ソース プロバイダーを使用して、PerformancePoint サービス でサポートされていない表形式のデータ ソースのデータを使用できます。

表形式のデータ ソース プロバイダーの主な機能は、データ テーブルを作成して、それにデータ ソースのデータを入力することです。 さらに列のマッピングを作成し、各列に含まれるデータの型 (ファクト、ディメンション、時間ディメンション) を定義します。 これにより、基本的な多次元構造が表形式のデータに適用されます。

このトピックの手順とコード例は、カスタム オブジェクト サンプルWSTabularDataSourceProvider クラスに基づいています。 プロバイダーは、指定された株式シンボル用の外部 Web サービスから株式を取得します。 プロバイダーは株式の履歴データをキャッシュ ファイルに格納します。これによりデータは時間単位で分割できます。 クラスの完全なコードについては、「コード例: SharePoint でカスタム PerformancePoint Services表形式データ ソースのデータ ソース プロバイダーを作成する」を参照してください。

テンプレートとして、サンプルのデータ ソース プロバイダーを使用することをお勧めします。 サンプルは、PerformancePoint サービス API のオブジェクトを呼び出す方法と、PerformancePoint サービス 開発のベスト プラクティスを示します。

ユーザー設定の PerformancePoint サービス 表形式のデータ ソースのデータ ソース プロバイダーを作成する

  1. PerformancePoint サービス をインストールするか、拡張機能で使用する DLL (手順 3 で表示) をコンピューターにコピーします。 手順については、「 クラス ライブラリを含む DLL」を参照してください。

  2. Visual Studio で、C# クラス ライブラリを作成します。 拡張機能のためのクラス ライブラリを既に作成している場合、新しい C# クラスを追加します。

    DLL には厳密な名前で署名する必要があります。 さらに、DLL によって参照されたすべてのアセンブリが厳密な名前を持つことを確認してください。 厳密な名前でアセンブリに署名する方法と、公開キーと秘密キーのペアを作成する方法については、「 方法: 公開/秘密キー ペアを作成する」を参照してください。

  3. 以下の PerformancePoint サービス DLL をアセンブリ参照としてプロジェクトに追加します。

  • Microsoft.PerformancePoint.Scorecards.Client.dll

  • Microsoft.PerformancePoint.Scorecards.DataSourceProviders.Standard.dll

    サンプル データ ソース プロバイダーには、System.Core.dll、System.ServiceModel.dll、System.Web.dll、System.Web.Services.dll、および System.Xml.Linq.dll へのアセンブリ参照も含まれます。 拡張機能の機能によっては、その他のプロジェクト参照が必要になることがあります。

  1. アドレス にある Web サービスを参照する http://www.webservicex.net/stockquote.asmx という名前のサービス参照を追加します。 これは、サンプル データ ソース用の株価を提供する Web サービスです。

  2. サンプルの BasicTabularDataSourceProvider クラスおよび SampleDSCacheHandler クラスをプロジェクトに追加します。 BasicTabularDataSourceProvider は、表形式のデータ ソース プロバイダーの基本クラスである TabularDataSourceProvider クラスから継承します。

    サンプル データ ソースでは、 TabularDataSourceProvider が実装していないオーバーライドされた抽象メソッドのコンテナーとして クラスも使用されます ( GetDatabaseNames()GetCubeNameInfos()GetCubeNameInfos()GetCubeMetaDataValidate() )。

  3. プロバイダー クラスで、以下の PerformancePoint サービス 名前空間のために using ディレクティブを追加します。

  1. BasicTabularDataSourceProvider クラスから継承します。

  2. 変数を宣言し、株式シンボルの解析、格納、取得に使用するプロパティ、キャッシュ ファイルの場所、プロキシ サーバーの URI を定義します。

  3. IsConnectionStringSecure プロパティをオーバーライドします。 このプロパティは、PerformancePoint Servicesでは使用されませんが、必要に応じてカスタム アプリケーションを使用して、接続文字列がセキュリティ リスクを伴う可能性のある情報を公開するかどうかを識別するためのものです。

    拡張機能によってユーザー名、パスワードなどの機密情報がデータ ソースの接続文字列に格納される場合は、 true を返します。 機密情報が格納されないか、データ ソースで接続文字列が使用されない場合は、 false を返します。

  4. GetId() メソッドをオーバーライドして、プロバイダーの一意の識別子を返します。 GetId() は、カスタム データ ソース プロバイダー用の PerformancePoint サービス web.config ファイルに登録されている key 属性と同じ文字列を返す必要があります。

  5. SetDataSource メソッドをオーバーライドして、列マッピングを定義します。 SetDataSource は、 CreateDataColumnMappings メソッドを呼び出し、 FactDimensionTimeDimension の型としてデータ ソース列を定義します。

    SetDataSource はさらに、株式シンボル、キャッシュ ファイルの場所、およびプロキシ alsoサーバー アドレスを、ユーザー設定のデータ ソース オブジェクトの CustomData プロパティから取得します。 これらの値は、サンプル データ ソース エディターのダッシュボード作成者によって定義されます。

  6. GetDataSet() メソッドをオーバーライドして、データ ソースからデータを格納する DataSet オブジェクトを作成します。 サンプル データ ソース プロバイダーは FillResultsTable メソッドおよび GetLiveQuote メソッドを使用して、データ テーブルに Web サービスからのデータを入力します。

コード例: SharePoint のユーザー設定の PerformancePoint サービス の表形式データ ソースのデータ ソース プロバイダーを作成する

以下のコード例のクラスでは、外部 Web サービスから株価を取得する表形式のデータ ソース プロバイダーを作成し、データを表形式に変換します。

このコード例をコンパイルする前に、「カスタム PerformancePoint Services表形式データ ソースのデータ ソース プロバイダーを作成する」の説明に従って開発環境を構成する必要があります。


using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.PerformancePoint.Scorecards;
using Microsoft.PerformancePoint.Scorecards.ServerCommon;
using Microsoft.PerformancePoint.SDK.Samples.StockQuotes;
using System.ServiceModel;

namespace Microsoft.PerformancePoint.SDK.Samples.SampleDataSource
{

    // Represents the class that defines the sample data source provider.
    // It inherits from the BasicTabularDataSourceProvider class, which
    // contains overridden abstract methods that are not implemented.
    public class WSTabularDataSourceProvider : BasicTabularDataSourceProvider
    {
        #region Constants
        private const int StockSymbolsIndex = 0;
        private const int CacheFileLocationIndex = 1;
        private const int ProxyAddressIndex = 2;
        #endregion

        #region Properties

        // This property stores the stock symbols that are used
        // to query the Web service.
        // Its value is obtained by parsing the CustomData property
        // of the data source object. 
        private string[] StockSymbols
        {
            get;
            set;
        }

        // The address of the proxy server.
        private Uri ProxyAddress
        {
            get;
            set;
        }

        // This property is not used by PerformancePoint Services.
        // Its intended use is for custom applications to indicate
        // whether a provider stores sensitive information in the
        // connection string, such as user name and password.
        // This sample does not, so it returns false. 
        public override bool IsConnectionStringSecure
        {
            get { return false; }
        }
        #endregion

        #region Overridden methods

        // The source name for your data source. This value must match the key
        // attribute that is registered in the web.config file.
        public override string GetId()
        {
            return "WSTabularDataSource";
        }

        // Add column mappings for the sample columns if they do not exist.
        // Column mappings may be missing if the custom data source has never
        // been edited or if the workspace was not refreshed, which saves
        // changes to the server.
        public override void SetDataSource(DataSource dataSource)
        {

            base.SetDataSource(dataSource);

            // Check for symbols stored in the CustomData
            // property of the data source.
            if (null == dataSource ||
                 string.IsNullOrEmpty(dataSource.CustomData))
            {

                // Create a symbol for testing purposes.
                StockSymbols = new[] { "MSFT" };
            }
            else
            {
                string[] splitCustomData = dataSource.CustomData.Split('&');
                if (splitCustomData.Length > 2)
                {
                    StockSymbols = splitCustomData[StockSymbolsIndex].ToUpper().Split(',');
                    for (int iLoop = 0; iLoop < StockSymbols.Length; iLoop++)
                    {
                        StockSymbols[iLoop] = StockSymbols[iLoop].Trim();
                    }

                    SampleDSCacheHandler.CacheFileLocation = splitCustomData[CacheFileLocationIndex];
                    ProxyAddress = new Uri(splitCustomData[ProxyAddressIndex]);
                }
            }

            // Check whether column mappings exist. Do not overwrite them.
            if (dataSource.DataTableMapping.ColumnMappings.Count == 0)
            {
                dataSource.DataTableMapping = CreateDataColumnMappings();
            }
        }

        // Get the data from the data source.
        // GetDataSet contains the core logic for the provider.
        public override DataSet GetDataSet()
        {

            // Create a dataset and a data table to store the data.
            DataSet resultSet = new DataSet();
            DataTable resultTable = resultSet.Tables.Add();

            // Define column names and the type of data that they contain. 
            resultTable.Columns.Add("Symbol", typeof(string));
            resultTable.Columns.Add("Value", typeof(float));
            resultTable.Columns.Add("P-E Ratio", typeof(float));
            resultTable.Columns.Add("Percentage Change", typeof(float));
            resultTable.Columns.Add("Date", typeof(DateTime));

            FillResultTable(ref resultTable);

            return resultSet;
        }
        #endregion

        #region Internal methods

        // Fill the data table with the stock quote values from
        // the Web service and local cache file.
        protected void FillResultTable(ref DataTable resultsTable)
        {

            // Check the sematic validity of symbols (out of scope for this sample).
            if (null != StockSymbols &amp;&amp;
                StockSymbols.Length > 0 &amp;&amp;
                !string.IsNullOrEmpty(SampleDSCacheHandler.CacheFileLocation))
            {
                try
                {
                    if (!File.Exists(SampleDSCacheHandler.CacheFileLocation))
                    {

                        // Create the cache file.
                        XDocument doc = SampleDSCacheHandler.DefaultCacheFileContent;
                        doc.Save(@SampleDSCacheHandler.CacheFileLocation);
                    }

                    // Get real-time quotes and update cache file.
                    string wsResult = GetLiveQuote();

                    SampleDSCacheHandler.UpdateXMLCacheFile(wsResult);

                    // Check if a valid cache file location exists.
                    if (SampleDSCacheHandler.CacheFileContent != null)
                    {
                        var query = from c in SampleDSCacheHandler.CacheFileContent.Elements("StockQuotes").Elements("StockQuote")
                                    where StockSymbols.Contains(c.Attribute("Symbol").Value)
                                    select c;

                        foreach (var stockQuote in query)
                        {
                            DataRow row = resultsTable.NewRow();
                            row["Symbol"] = stockQuote.Attribute("Symbol").Value;
                            row["Value"] = stockQuote.Element("Value").Value;
                            row["Percentage Change"] = stockQuote.Element("PercentageChange").Value;
                            row["Date"] = stockQuote.Element("Date").Value;

                            decimal peRatio;

                            // Handle symbols that return 'N/A' for this field.
                            if (decimal.TryParse(stockQuote.Element("PERatio").Value, out peRatio))
                            {
                                row["P-E Ratio"] = peRatio;
                            }

                            resultsTable.Rows.Add(row);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ServerUtils.HandleException(ex);
                }
            }
        }

        // Get real-time quotes from the Web service.
        protected string GetLiveQuote()
        {
            EndpointAddress endpoint = new EndpointAddress("http://www.webservicex.net/stockquote.asmx");
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.ReceiveTimeout = new TimeSpan(0, 0, 120);
            binding.ProxyAddress = ProxyAddress;
            binding.UseDefaultWebProxy = false;

            StockQuotes.StockQuoteSoapClient wsStockQuoteService = new StockQuoteSoapClient(binding, endpoint);

            // Check the sematic validity of symbols (out of scope for this sample).
            if (null != StockSymbols &amp;&amp;
                StockSymbols.Length > 0)
            {
                try
                {
                    string quoteRequest = StockSymbols[0];
                    for (int iLoop = 1; iLoop < StockSymbols.Length; iLoop++)
                    {
                        quoteRequest = string.Format("{0}, {1}", quoteRequest, StockSymbols[iLoop]);
                    }

                    string wsResult = wsStockQuoteService.GetQuote(quoteRequest);
                    return wsResult;
                }
                catch (Exception ex)
                {
                    ServerUtils.HandleException(ex);
                }
            }
            return string.Empty;
        }

        // Create the column mappings.
        internal static DataTableMapping CreateDataColumnMappings()
        {
            DataTableMapping dtTableMapping = new DataTableMapping();

            // Define the data in the Symbol column as dimension data.
            dtTableMapping.ColumnMappings.Add(new DataColumnMapping
            {
                SourceColumnName = "Symbol",
                FriendlyColumnName = "Symbol",
                UniqueName = "Symbol",
                ColumnType = MappedColumnTypes.Dimension,
                FactAggregation = FactAggregations.None,
                ColumnDataType = MappedColumnDataTypes.String
            });

            // Define the data in the Value column as fact data.
            dtTableMapping.ColumnMappings.Add(new DataColumnMapping
            {
                SourceColumnName = "Value",
                FriendlyColumnName = "Value",
                UniqueName = "Value",
                ColumnType = MappedColumnTypes.Fact,
                FactAggregation = FactAggregations.Average,
                ColumnDataType = MappedColumnDataTypes.Number
            });

            // Define the data in the P-E Ratio column as fact data.
            dtTableMapping.ColumnMappings.Add(new DataColumnMapping
            {
                SourceColumnName = "P-E Ratio",
                FriendlyColumnName = "P-E Ratio",
                UniqueName = "P-E Ratio",
                ColumnType = MappedColumnTypes.Fact,
                FactAggregation = FactAggregations.Average,
                ColumnDataType = MappedColumnDataTypes.Number
            });

            // Define the data in the Percentage Change column as fact data.
            dtTableMapping.ColumnMappings.Add(new DataColumnMapping
            {
                SourceColumnName = "Percentage Change",
                FriendlyColumnName = "Percentage Change",
                UniqueName = "Percentage Change",
                ColumnType = MappedColumnTypes.Fact,
                FactAggregation = FactAggregations.Average,
                ColumnDataType = MappedColumnDataTypes.Number
            });

            // Define the Date column as a time dimension.
            dtTableMapping.ColumnMappings.Add(new DataColumnMapping
            {
                SourceColumnName = "Date",
                FriendlyColumnName = "Date",
                UniqueName = "Date",
                ColumnType = MappedColumnTypes.TimeDimension,
                FactAggregation = FactAggregations.None,
                ColumnDataType = MappedColumnDataTypes.DateTime
            });

            // Increase the granularity of the time dimension.
            dtTableMapping.DateAggregationType |= DateAggregationTypes.Quarter;
            dtTableMapping.DateAggregationType |= DateAggregationTypes.Month;
            dtTableMapping.DateAggregationType |= DateAggregationTypes.Week;
            dtTableMapping.DateAggregationType |= DateAggregationTypes.Day;

            return dtTableMapping;
        }
        #endregion
    }
}

次の手順

データ ソース プロバイダーとデータ ソース エディター (必要に応じてユーザー インターフェイスを含む) を作成した後、「方法: PerformancePoint Services拡張機能を手動で登録する」の説明に従って拡張機能をデプロイします

関連項目