Freigeben über


Gewusst wie: Erstellen von Anbietern für tabularische Datenquellen von PerformancePoint Services

Letzte Änderung: Dienstag, 30. August 2011

Datenquellenanbieter stellen eine Verbindung mit einer Datenquelle her, greifen auf deren Daten zu und geben dann Abfrageergebnisse zurück. PerformancePoint Services in Microsoft SharePoint Server 2010 verwendet Anbieter für tabellarische Datenquellen für den Zugriff auf Daten in Microsoft Excel- und Excel Services-Arbeitsmappen, SharePoint-Listen und Microsoft SQL Server-Tabellen.

Gilt für: SharePoint Server 2010

Sie können einen benutzerdefinierten Datenquellenanbieter erstellen, um Daten aus einer tabellarischen Datenquelle zu verwenden, die nicht von PerformancePoint Services unterstützt wird. Ein Anbieter für tabellarische Datenquellen hat in erster Linie die Funktion, eine Datentabelle zu erstellen und sie mit Daten aus der Datenquelle aufzufüllen. Außerdem erstellt er Spaltenzuordnungen, um den Datentyp der verschiedenen Spalten zu definieren (Fact, Dimension oder TimeDimension). Hiermit wird eine einfache mehrdimensionale Struktur auf die Tabellendaten angewendet.

Die Prozeduren und Codebeispiele in diesem Thema basieren auf der WSTabularDataSourceProvider-Klasse im Beispiel für benutzerdefinierte Objekte. Der Anbieter ruft Aktienkurse von einem externen Webdienst für angegebene Aktiensymbole ab. Historische Aktenkursdaten werden in einer Cachedatei gespeichert, wodurch die Daten zeitlich aufgeteilt werden können. Der vollständige Code für die Klasse befindet sich in diesem Thema im Abschnitt "Beispiel".

HinweisHinweis

Es wird empfohlen, den Beispiel-Datenquellenanbieter als Vorlage zu verwenden. In diesem Beispiel wird erläutert, wie Sie Objekte in der PerformancePoint Services-API aufrufen, und außerdem werden bewährte Methoden für die PerformancePoint Services-Entwicklung beschrieben.

Zum Erstellen eines Datenquellenanbieters führen Sie die folgenden beiden grundlegenden Verfahren aus:

  • Erstellen und Konfigurieren der Anbieterklasse

  • Definieren der Anbieterfunktionalität

Zum Erzeugen eines benutzerdefinierten Anbieters erstellen Sie zunächst die Anbieterklasse.

So erstellen und konfigurieren Sie die Anbieterklasse

  1. Installieren Sie PerformancePoint Services, oder kopieren Sie die von der Erweiterung verwendeten DLLs (siehe Schritt 3) auf den Computer. Anweisungen hierzu finden Sie unter PerformancePoint-Dienste-DLLs in Entwicklungsszenarios.

  2. Erstellen Sie in Visual Studio eine C#-Klassenbibliothek. Sollten Sie bereits eine Klassenbibliothek für die Erweiterung erstellt haben, fügen Sie eine neue C#-Klasse hinzu.

  3. Fügen Sie dem Projekt die folgenden PerformancePoint Services-DLLs als Assemblyverweise hinzu:

    • Microsoft.PerformancePoint.Scorecards.Client.dll

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

    Der Beispiel-Datenquellenanbieter enthält ebenfalls Assemblyverweise auf System.Core.dll, System.ServiceModel.dll, System.Web.dll, System.Web.Services.dll und System.Xml.Linq.dll. Je nach Funktionalität Ihrer Erweiterung sind u. U. weitere Projektverweise erforderlich.

  4. Fügen Sie einen Dienstverweis mit dem Namen StockQuotes hinzu, mit dem auf den Webdienst mit der Adresse http://www.webservicex.net/stockquote.asmx verwiesen wird. Dieser Webdienst liefert Aktienkurse für die Beispieldatenquelle.

  5. Fügen Sie dem Projekt die Klassen BasicTabularDataSourceProvider und SampleDSCacheHandler aus dem Beispiel hinzu. BasicTabularDataSourceProvider erbt von der TabularDataSourceProvider-Klasse, die eine Basisklasse für Anbieter für tabellarische Datenquellen ist.

    Die Klasse wird von der Beispieldatenquelle auch als Container für die überschriebenen abstrakten Methoden verwendet, die von TabularDataSourceProvider nicht implementiert werden (GetDatabaseNames(), GetCubeNames(), GetCubeNameInfos(), GetCubeMetaData und Validate()).

  6. Fügen Sie in der Anbieterklasse using-Direktiven für die folgenden PerformancePoint Services-Namespaces hinzu:

    Je nach Funktionalität der Erweiterung sind u. U. andere using-Direktiven erforderlich.

  7. Erben Sie von der BasicTabularDataSourceProvider-Klasse.

Nachdem Sie die Anbieterklasse erstellt und konfiguriert haben, müssen Sie die Funktionalität des Anbieters definieren.

So definieren Sie die Anbieterfunktionalität

  1. Deklarieren Sie Variablen, und definieren Sie Eigenschaften, mit denen Sie Aktiensymbole, den Speicherort für die Cachedatei sowie den URI des Proxyservers analysieren, speichern und abrufen.

  2. Überschreiben Sie die IsConnectionStringSecure-Eigenschaft. Diese Eigenschaft wird nicht von PerformancePoint Services verwendet, ist aber optional für benutzerdefinierte Anwendungen gedacht, um festzustellen, ob mit einer Verbindungszeichenfolge Informationen verfügbar gemacht werden, die ein Sicherheitsrisiko darstellen könnten.

    Es wird true zurückgegeben, wenn von der Erweiterung vertrauliche Informationen (z. B. ein Benutzername oder Kennwort) in der Verbindungszeichenfolge für Ihre Datenquelle gespeichert werden. false wird zurückgegeben, wenn keine vertraulichen Informationen gespeichert werden oder wenn von der Datenquelle keine Verbindungszeichenfolge verwendet wird.

  3. Überschreiben Sie die GetId()-Methode, um den eindeutigen Bezeichner für Ihren Anbieter zurückzugeben. GetId() muss dieselbe Zeichenfolge wie das key-Attribut zurückgeben, das in der Datei web.config von PerformancePoint Services für den benutzerdefinierten Datenquellenanbieter registriert ist.

  4. Überschreiben Sie die SetDataSource-Methode, um Spaltenzuordnungen zu definieren. SetDataSource ruft die CreateDataColumnMappings-Methode auf, um Datenquellenspalten vom Typ Fact, Dimension und TimeDimension zu definieren.

    Mit SetDataSource werden auch die Aktiensymbole, der Speicherort für die Cachedatei und die Proxyserveradresse aus der CustomData-Eigenschaft des benutzerdefinierten Datenquellenobjekts abgerufen. Diese Werte werden von Dashboardautoren im Beispiel-Datenquellen-Editor definiert.

  5. Überschreiben Sie die GetDataSet()-Methode, um ein DataSet-Objekt zum Speichern der Daten aus der Datenquelle zu erstellen. Der Beispiel-Datenquellenanbieter verwendet die Methoden FillResultsTable und GetLiveQuote zum Auffüllen einer Datentabelle mit Daten eines Webdiensts.

    Nächster Schritt: Nachdem Sie einen Datenquellenanbieter und Datenquellen-Editor (einschließlich ggf. der zugehörigen Benutzeroberfläche) erstellt haben, stellen Sie die Erweiterung wie unter Gewusst wie: Manuelles Registrieren von PerformancePoint-Dienste-Erweiterungen beschrieben bereit. Anweisungen zum Installieren und Konfigurieren der Beispiel-Datenquellenerweiterung finden Sie im Abschnitt "Installieren der Beispielobjekte für Berichte, Filter und Datenquellen" unter Codebeispiel: Benutzerdefinierte Objekte für Berichte, Filter und tabulierte Datenquellen.

Beispiel

Mithilfe der Klasse im folgenden Codebeispiel wird ein Anbieter für tabellarische Datenquellen erstellt, mit dem Aktienkurse von einem externen Webdienst abgerufen und die Daten anschließend in ein tabellarisches Format transformiert werden.

HinweisHinweis

Bevor Sie dieses Codebeispiel kompilieren können, müssen Sie die Entwicklungsumgebung wie unter So erstellen und konfigurieren Sie die Anbieterklasse beschrieben konfigurieren.

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
    }
}

Code wird kompiliert

Bevor Sie dieses Codebeispiel kompilieren können, müssen Sie die Entwicklungsumgebung wie unter So erstellen und konfigurieren Sie die Anbieterklasse beschrieben konfigurieren.

Sicherheit

Sie müssen die DLL mit einem starken Namen signieren. Stellen Sie außerdem sicher, dass alle Assemblys, auf die von der DLL verwiesen wird, ebenfalls starke Namen haben. Informationen dazu, wie Sie eine Assembly mit einem starken Namen signieren und ein öffentliches/privates Schlüsselpaar erstellen, finden Sie unter How to: Create a Public/Private Key Pair.

Siehe auch

Aufgaben

Gewusst wie: Erstellen von Editoren für tabularische Datenquellen von PerformancePoint Services

Weitere Ressourcen

Erstellen von benutzerdefinierten Objekten für PerformancePoint Services

Codebeispiele für PerformancePoint Services in SharePoint Server 2010