Benutzerdefinierte Funktionen und gespeicherte Prozeduren

Mit ADOMD.NET-Serverobjekten können Sie eine benutzerdefinierte Funktion (UDF) oder gespeicherte Prozeduren für Microsoft SQL Server Analysis Services erstellen, die mit Metadaten und Daten vom Server interagieren. Diese prozessinternen Methoden werden durch Multidimensional Expressions (MDX)- oder Data Mining Extensions (DMX)-Anweisungen aufgerufen, um zusätzliche Funktionen bereitzustellen, die nicht den Wartezeiten eines Netzwerks unterworfen sind.

UDF-Beispiele

Eine benutzerdefinierte Funktion (UDF) ist eine Methode, die im Zusammenhang mit einer MDX- oder DMX-Anweisung aufgerufen wird, eine beliebige Anzahl an Parametern unterstützt und jede Art von Daten zurückgeben kann.

Eine mit MDX erstellte benutzerdefinierte Funktion ist mit einer für DMX erstellten vergleichbar. Der Hauptunterschied besteht darin, dass bestimmte Eigenschaften des Context-Objekts, wie zum Beispiel die Eigenschaften CurrentCube und CurrentMiningModel, nur für die eine oder die andere Skriptsprache verfügbar sind.

Die folgenden Beispiele zeigen, wie man mit einer benutzerdefinierten Funktion eine Knotenbeschreibung zurückgibt, Tupeln filtert und einen Filter auf ein Tupel anwendet.

Zurückgeben einer Knotenbeschreibung

Im folgenden Beispiel wird eine benutzerdefinierte Funktion erstellt, mit der die Knotenbeschreibung für einen bestimmten Knoten zurückgegeben wird. Die benutzerdefinierte Funktion verwendet den derzeitigen Kontext, in dem sie ausgeführt wird, und ruft den Knoten mithilfe einer DMX FROM-Klausel aus dem aktuellen Miningmodell ab.

public string GetNodeDescription(string nodeUniqueName)
{
   return Context.CurrentMiningModel.GetNodeFromUniqueName(nodeUniqueName).Description;
}

Nach der Bereitstellung kann das vorherige UDF-Beispiel durch folgenden DMX-Ausdruck, der den wahrscheinlichsten Vorhersageknoten abruft, aufgerufen werden. Die Beschreibung enthält Informationen, in denen die Bedingungen beschrieben werden, die den Vorhersageknoten bilden.

select Cluster(), SampleAssembly.GetNodeDescription( PredictNodeId(Cluster()) ) FROM [Customer Clusters]

Zurückgeben von Tupeln

Im folgenden Beispiel werden mit einem Satz und einer Rückgabezahl Tupeln nach dem Zufallsprinzip aus dem Satz abgerufen, wodurch schließlich eine Teilmenge zurückgegeben wird:

public Set RandomSample(Set set, int returnCount)
{
   //Return the original set if there are fewer tuples
   //in the set than the number requested.
   if (set.Tuples.Count <= returnCount)
      return set;

   System.Random r = new System.Random();
   SetBuilder returnSet = new SetBuilder();

   //Retrieve random tuples until the return set is filled.
   int i = set.Tuples.Count;
   foreach (Tuple t in set.Tuples)
   {
      if (r.Next(i) < returnCount)
      {
         returnCount--;
         returnSet.Add(t);
      }
      i--;
      //Stop the loop if we have enough tuples.
      if (returnCount == 0)
         break;
   }
   return returnSet.ToSet();
}

Das vorherige Beispiel wird in folgendem MDX-Beispiel aufgerufen. In diesem MDX-Beispiel werden fünf zufällige Bundesstaaten oder Provinzen aus der Datenbank Adventure Works abgerufen.

SELECT SampleAssembly.RandomSample([Geography].[State-Province].Members, 5) on ROWS, 
[Date].[Calendar].[Calendar Year] on COLUMNS
FROM [Adventure Works]
WHERE [Measures].[Reseller Freight Cost]

Anwenden eines Filters auf ein Tupel

In folgendem Beispiel wird eine benutzerdefinierte Funktion definiert, mit der in einem Satz unter Verwendung des Expression-Objekts ein Filter auf jedes Tupel in dem Satz angewendet wird. Alle Tupel, die dem Filter entsprechen, werden einem zurückgegebenen Satz hinzugefügt.

public static Set FilterSet(Set set, String filterExpression)
{
    Expression expr = new Expression(filterExpression);

    SetBuilder resultSetBuilder = new SetBuilder();

    foreach (Tuple tuple in set)
    {
        if ((bool)(expr.Calculate(tuple)))
        {
            resultSetBuilder.Add(tuple);
        }
    }

    return resultSetBuilder.ToSet();
}

Das vorangegangene Beispiel wird in folgendem MDX-Beispiel aufgerufen, bei dem der Satz auf mit 'A' beginnende Städte gefiltert wird.

Select Measures.Members on Rows,
SampleAssembly.FilterSet([Customer].[Customer Geography].[City], "[Customer].[Customer Geography].[City].CurrentMember.Name < 'B'") on Columns
From [Adventure Works]

Beispiel für gespeicherte Prozeduren

In folgendem Beispiel verwendet eine MDX-basierte, gespeicherte Prozedur AMO, um bei Bedarf Partitionen für Internet Sales zu erstellen.

public static void CreateInternetSalesMeasureGroupPartitions()
{
    //Check the current state of the data warehouse and 
    //create partitions with AMO if necessary
    #region Retrieve order date of last sales transaction

    // Open a connection to the data warehouse
    // TODO: Change the first string parameter to reflect the right server\instance.
    SqlConnection conn = new SqlConnection(string.Format("data source={0};initial catalog={1};Integrated Security=SSPI", "server\\instance", Context.CurrentDatabaseName));
    conn.Open();

    // Create a command
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = conn;

    // Get the order date key of the last internet sale
    int lastInternetSaleDateKey = 0;
    cmd.CommandText = "select max(OrderDateKey) from FactInternetSales";
    lastInternetSaleDateKey = (int)cmd.ExecuteScalar();

    // Get the order date key of the last reseller sale
    int lastResellerSaleDateKey = 0;
    cmd.CommandText = "select max(OrderDateKey) from FactResellerSales";
    lastResellerSaleDateKey = (int)cmd.ExecuteScalar();
    #endregion

    #region Create partitions

    // Connect to the calling session
    Server svr = new Server();
    svr.Connect("*");

    // Get the Adventure Works cube
    Database db = svr.Databases.GetByName(Context.CurrentDatabaseName);
    Cube cube = db.Cubes[0];

    MeasureGroup mg;
    int maxOrderDateKey;

    mg = cube.MeasureGroups.GetByName("Internet Sales");
    maxOrderDateKey = 0;
    foreach (Partition part in mg.Partitions)
    {
        maxOrderDateKey = Math.Max(maxOrderDateKey, Convert.ToInt32(
            part.Annotations.Find("LastOrderDateKey").Value.Value,
            System.Globalization.CultureInfo.InvariantCulture));
    }

    if (maxOrderDateKey < lastInternetSaleDateKey)
    {
        Partition part = mg.Partitions.Add("Internet_Sales_"
            + lastInternetSaleDateKey);
        part.StorageMode = StorageMode.Molap;
        part.Source = new QueryBinding(db.DataSources[0].ID,
            "SELECT * FROM [dbo].[FactInternetSales] WHERE OrderDateKey > '"
            + maxOrderDateKey + "' and OrderDateKey <= '" + lastInternetSaleDateKey + "'");
        part.Annotations.Add("LastOrderDateKey", Convert.ToString(lastInternetSaleDateKey,
            System.Globalization.CultureInfo.InvariantCulture));
        part.Update();
        part.Process();
    }

    svr.Disconnect();

    #endregion
}