Funções definidas pelo usuário e procedimentos armazenados

Com ADOMD.NET objetos de servidor, pode criar funções definidas pelo utilizador (UDF) ou procedimentos armazenados para os Microsoft SQL Server Analysis Services que interagem com metadados e dados do servidor. Estes métodos em processo são chamados através de instruções de Expressões Multidimensionais (MDX) ou Extensões de Mineração de Dados (DMX) para fornecer funcionalidades adicionais sem as latências associadas às comunicações em rede.

Exemplos da UDF

Um UDF é um método que pode ser chamado no contexto de uma instrução MDX ou DMX, pode tomar qualquer número de parâmetros e pode devolver qualquer tipo de dados.

Um UDF criado usando MDX é semelhante a um criado para DMX. A principal diferença é que certas propriedades do objeto Microsoft.AnalysisServices.AdomdServer.Context, como as propriedades Microsoft.AnalysisServices.AdomdServer.Context.CurrentCube e Microsoft.AnalysisServices.AdomdServer.Context.CurrentMiningModel, estão disponíveis apenas para uma linguagem de scripting ou outra.

Os exemplos seguintes mostram como usar um UDF para devolver uma descrição de nó, filtrar tuplas e aplicar um filtro a uma tupla.

Devolver uma descrição de nó

O exemplo seguinte cria uma FUD (Função Definida pelo Utilizador) que devolve a descrição do nó para um nó especificado. O UDF utiliza o contexto atual em que está a ser executado e utiliza uma cláusula DMX FROM para recuperar o nó do modelo de mineração atual.

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

Uma vez implantado, o exemplo UDF anterior pode ser chamado pela expressão DMX seguinte, que recupera o nó de predição mais provável. A descrição contém informações que descrevem as condições que constituem o nó de previsão.

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

Tuplas de Regresso

O exemplo seguinte recebe um conjunto e um número a devolver, e obtém aleatoriamente tuplas do conjunto, retornando um subconjunto final:

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();  
}  

O exemplo anterior é invocado no seguinte exemplo MDX. Neste exemplo de MDX, cinco estados ou províncias aleatórios são recuperados da base de dados Adventure Works .

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

Aplicar um Filtro a uma Tupla

No exemplo seguinte, é definido um UDF que toma um conjunto e aplica um filtro a cada tupla do conjunto, usando o objeto Expression. Quaisquer tuplas que se ajustem ao filtro serão adicionadas a um conjunto que é devolvido.

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();
}

O exemplo anterior é chamado no seguinte exemplo de MDX, que filtra o conjunto para cidades cujos nomes começam por 'A'.

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

Exemplo de Procedimento Armazenado

No exemplo seguinte, um procedimento armazenado baseado em MDX utiliza o AMO para criar partições, se necessário, para vendas na Internet.

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
}