Поделиться через


Определяемые пользователем функции и хранимые процедуры

Серверные объекты ADOMD.NET позволяют создавать определяемые пользователем функции или хранимые процедуры для служб MicrosoftSQL ServerAnalysis Services, которые взаимодействуют с метаданными и данными с сервера. Эти внутрипроцессные методы вызываются при помощи инструкций на языке MDX или DMX для обеспечения дополнительной функциональности без задержек, связанных с работой линий связи.

Примеры определяемых пользователем функций

UDF — это метод, который можно вызывать в контексте инструкции MDX или DMX, он может принимать любое количество параметров и возвращать любой тип данных.

Определяемая пользователем функция, созданная при помощи языка MDX, похожа на функцию, созданную на языке DMX. Основная разница заключается в том, что определенные свойства объекта Context, например свойства CurrentCube и CurrentMiningModel, можно использовать только в одном из двух этих языков сценариев.

Следующие примеры демонстрируют использования определяемой пользователем функции для возвращения описания узла, фильтрации кортежей и применения фильтра к кортежу.

Возвращение описания узла

В следующем примере создается определяемая пользователем функция, которая возвращает описание указанного узла. Эта функция использует текущий контекст, в котором она выполняется, а также предложение DMX FROM для извлечения узла из текущей модели интеллектуального анализа данных.

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

После развертывания описанный выше пример определяемой пользователем функции можно будет вызвать следующей инструкцией DMX, которая извлекает наиболее вероятный узел прогнозирования. В описании приводятся сведения, характеризующие условия, составляющие узел прогнозирования.

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

Возвращение кортежей

Следующий пример принимает набор и счетчик возврата, а также случайным образом извлекает кортежи из набора, возвращая конечное подмножество.

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

Описанная выше функция вызывается в следующем примере MDX. В этом примере MDX из базы данных Adventure Works извлекаются пять случайных государств или провинций.

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

Применение фильтра к кортежу

В следующем примере создается определяемая пользователем функция, которая принимает набор и при помощи объекта «Expression» применяет фильтр к каждому кортежу в наборе. В возвращаемый набор будут добавлены все кортежи, соответствующие фильтру.

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

Описанная выше функция вызывается в следующем примере MDX, где набор фильтруется по городам, название которых начинается с «А».

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

Пример хранимой процедуры

В следующем примере хранимая процедура, написанная на языке MDX при необходимости использует объект AMO для создания секций для узла «Продажи через Интернет».

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
}