次の方法で共有


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

最終更新日: 2011年8月30日

適用対象: SharePoint Server 2010

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

適用先: PerformancePoint Services for SharePoint Server (Enterprise バージョン)

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

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

注意

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

データ ソース プロバイダーを作成するときは、次の 2 つの基本的な手順を実行します。

  • プロバイダー クラスの作成と設定

  • プロバイダー機能の定義

カスタム プロバイダーを作成するには、プロバイダー クラスの作成から始めます。

プロバイダー クラスを作成して設定するには

  1. PerformancePoint Services をインストールするか、拡張機能が使用する (手順 3. で示した) DLL をコンピューターにコピーします。方法は、「開発シナリオで使用される PerformancePoint Services DLL」を参照してください。

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

  3. プロジェクトに、アセンブリ参照として以下の PerformancePoint Services 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 へのアセンブリ参照も含まれます。拡張機能の機能によっては、その他のプロジェクト参照が必要になることがあります。

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

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

    サンプル データ ソースは、TabularDataSourceProvider が実装しない無効にされた抽象メソッド (GetDatabaseNames()GetCubeNames()GetCubeNameInfos()GetCubeMetaData、および Validate()) のコンテナーとしてクラスを使用します。

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

    拡張機能の機能によっては、その他の using ディレクティブが必要になることがあります。

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

プロバイダー クラスを作成して設定した後で、プロバイダーの機能を定義する必要があります。

プロバイダーの機能を定義するには

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

  2. IsConnectionStringSecure プロパティを上書きします。このプロパティは PerformancePoint Services には使用されません。このプロパティは、セキュリティ リスクをもたらす情報を接続文字列が公開するかどうかを特定するために、カスタム アプリケーションが任意に使用します。

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

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

  4. SetDataSource メソッドを上書きして、列のマッピングを定義します。SetDataSource は、CreateDataColumnMappings メソッドを呼び出し、FactDimensionTimeDimension の型としてデータ ソース列を定義します。

    SetDataSource はさらに、株式シンボル、キャッシュ ファイルの場所、およびプロキシ サーバー アドレスを、列データ ソース オブジェクトの CustomData プロパティから取得します。

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

    次の手順: データ ソース プロバイダーとデータ ソース エディター (必要に応じて、ユーザー インターフェイスも) を作成したら、「[方法] PerformancePoint Services の拡張機能を手動で登録する」で説明されているように、拡張機能を展開します。データ ソースの拡張機能のサンプルをインストールする方法については、「コード サンプル: カスタム レポート、フィルター、および表形式データ ソース オブジェクト」の「サンプルのレポート、フィルター、およびデータ ソース オブジェクトのインストール」セクションを参照してください。

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

注意

このコード例をコンパイルする前に、「プロバイダー クラスを作成して設定するには」で説明しているように、開発環境を設定する必要があります。

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 &&
                StockSymbols.Length > 0 &&
                !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 &&
                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
    }
}

コードのコンパイル

このコード例をコンパイルする前に、「プロバイダー クラスを作成して設定するには」で説明しているように、開発環境を設定する必要があります。

セキュリティ

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

関連項目

タスク

[方法] PerformancePoint Services の表形式データ ソースのエディターを作成する

その他の技術情報

PerformancePoint Services のカスタム オブジェクトを作成する

SharePoint Server 2010 の PerformancePoint Services のコード例