Programowanie obiektów zaawansowanych OLAP AMO

Dotyczy: SQL Server Analysis Services Azure Analysis Services Fabric/Power BI Premium

W tym temacie opisano szczegóły programowania obiektów zarządzania analizami (AMO) zaawansowanych obiektów OLAP.

Obiekty działania

Klasy akcji służą do tworzenia aktywnej odpowiedzi podczas przeglądania niektórych obszarów modułu. Obiekty akcji można zdefiniować przy użyciu funkcji AMO, ale są używane z poziomu aplikacji klienckiej, która przegląda dane. Akcje mogą być różne typy i muszą być tworzone zgodnie z ich typem. Akcje mogą być następujące:

  • Akcje przeglądania szczegółowego, które zwracają zestaw wierszy reprezentujących bazowe dane wybranych komórek modułu, w którym odbywa się akcja.

  • Akcje raportowania, które zwracają raport skojarzony z wybraną sekcją kostki, w której odbywa się akcja.

  • Akcje standardowe, które zwracają element akcji (URL, HTML, DataSet, RowSet i inne elementy), które są skojarzone z wybraną sekcją modułu, w którym odbywa się akcja.

Utworzenie obiektu akcji wymaga wykonania następujących kroków:

  1. Utwórz obiekt akcji pochodnej i wypełnij podstawowe atrybuty.

    Poniżej przedstawiono podstawowe atrybuty: typ akcji, typ docelowy lub sekcję modułu, docelowy lub konkretny obszar modułu, w którym jest dostępna akcja, podpis i gdzie podpis jest wyrażeniem MDX.

  2. Uzupełnij określone atrybuty typu akcji.

    Atrybuty różnią się w zależności od trzech typów akcji, zobacz poniższy przykładowy kod, aby uzyskać informacje o parametrach.

  3. Dodaj akcję do kolekcji kostek i zaktualizuj kostkę. Akcja nie jest obiektem aktualizowalnym.

Testowanie akcji wymaga innej aplikacji programowej. Możesz przetestować akcję w programie Visual Studio.

Poniższy przykładowy kod replikuje trzy różne akcje z przykładu projektu Adventure Works Analysis Services. Możesz odróżnić akcje, ponieważ te wprowadzone przy użyciu poniższego przykładu zaczynają się od "Moje".

static public void CreateActions(Cube cube)  
{  
    #region Adding a drillthrough action  
    // Verify That action exists and drop it  
    if (cube.Actions.ContainsName("My Reseller Details"))  
        cube.Actions.Remove("My Drillthrough Action",true);  
  
    //Create a Drillthrough action  
    DrillThroughAction dtaction = new DrillThroughAction("My Reseller Details", "My Drillthrough Action");  
  
    //Define the Action  
    dtaction.Type = ActionType.DrillThrough;  
    dtaction.TargetType = ActionTargetType.Cells;  
    dtaction.Target = "MeasureGroupMeasures(\"Reseller Sales\")";  
    dtaction.Caption = "My Drillthrough...";  
    dtaction.CaptionIsMdx = false;  
  
    #region create drillthrough action specifics  
    //Adding Drillthrough columns  
    //Adding Measure columns to the drillthrough  
    MeasureGroup mg = cube.MeasureGroups.FindByName("Reseller Sales");  
    MeasureBinding mb1 = new MeasureBinding();  
    mb1.MeasureID = mg.Measures.FindByName( "Reseller Sales Amount").ID;  
    dtaction.Columns.Add(mb1);  
  
    MeasureBinding mb2 = new MeasureBinding();  
    mb2.MeasureID = mg.Measures.FindByName("Reseller Order Quantity").ID;  
    dtaction.Columns.Add(mb2);  
  
    MeasureBinding mb3 = new MeasureBinding();  
    mb3.MeasureID = mg.Measures.FindByName("Reseller Unit Price").ID;  
    dtaction.Columns.Add(mb3);  
  
    //Adding Dimension Columns to the drillthrough  
    CubeAttributeBinding cb1 = new CubeAttributeBinding();  
    cb1.CubeID = cube.ID;  
    cb1.CubeDimensionID = cube.Dimensions.FindByName("Reseller").ID;  
    cb1.AttributeID = "Reseller Name";  
    cb1.Type = AttributeBindingType.All;  
    dtaction.Columns.Add(cb1);  
  
    CubeAttributeBinding cb2 = new CubeAttributeBinding();  
    cb2.CubeID = cube.ID;  
    cb2.CubeDimensionID = cube.Dimensions.FindByName("Product").ID;  
    cb2.AttributeID = "Product Name";  
    cb2.Type = AttributeBindingType.All;  
    dtaction.Columns.Add(cb2);  
    #endregion  
  
    //Add the defined action to the cube  
    cube.Actions.Add(dtaction);  
    #endregion  
  
    #region Adding a Standard action  
    // Verify That action exists and drop it  
    if (cube.Actions.ContainsName("My City Map"))  
        cube.Actions.Remove("My Action", true);  
  
    //Create a Drillthrough action  
    StandardAction stdaction = new StandardAction("My City Map", "My Action");  
  
    //Define the Action  
    stdaction.Type = ActionType.Url;  
    stdaction.TargetType = ActionTargetType.AttributeMembers;  
    stdaction.Target = "[Geography].[City]";  
    stdaction.Caption = "\"My View Map for \" + [Geography].[City].CurrentMember.Member_Caption + \"...\"";  
    stdaction.CaptionIsMdx = true;  
  
    #region create standard action specifics  
    stdaction.Expression = "\"http://maps.msn.com/home.aspx?plce1=\" + " +  
        "[Geography].[City].CurrentMember.Name + \",\" + " +  
        "[Geography].[State-Province].CurrentMember.Name + \",\" + " +  
        "[Geography].[Country].CurrentMember.Name + " +  
        "\"&regn1=\" + " +  
        "Case " +  
            "When [Geography].[Country].CurrentMember Is " +  
                    "[Geography].[Country].&[Australia] " +  
                "Then \"3\" " +  
            "When [Geography].[Country].CurrentMember Is " +  
                    "[Geography].[Country].&[Canada] " +  
                "Or [Geography].[Country].CurrentMember Is " +  
                    "[Geography].[Country].&[United States] " +  
                "Then \"0\" " +  
                "Else \"1\" " +  
        "End ";  
    #endregion  
  
    //Add the defined action to the cube  
    cube.Actions.Add(stdaction);  
  
    #endregion  
  
    #region Adding a Reporting action  
    // Verify That action exists and drop it  
    if (cube.Actions.ContainsName("My Sales Reason Comparisons"))  
        cube.Actions.Remove("My Report Action", true);  
  
    //Create a Report action  
    ReportAction rsaction = new ReportAction("My Sales Reason Comparisonsp", "My Report Action");  
  
    //Define the Action  
    rsaction.Type = ActionType.Report;  
    rsaction.TargetType = ActionTargetType.AttributeMembers;  
    rsaction.Target = "[Product].[Category]";  
    rsaction.Caption = "\"My Sales Reason Comparisons for \" + [Product].[Category].CurrentMember.Member_Caption + \"...\"";  
    rsaction.CaptionIsMdx = true;  
  
    #region create Report action specifics  
    rsaction.ReportServer = "MyRSSamplesServer";  
    rsaction.Path = "ReportServer?/AdventureWorks Sample Reports/Sales Reason Comparisons";  
    rsaction.ReportParameters.Add("ProductCategory", "UrlEscapeFragment( [Product].[Category].CurrentMember.UniqueName )");  
    rsaction.ReportFormatParameters.Add("rs:Command", "Render");  
    rsaction.ReportFormatParameters.Add("rs:Renderer", "HTML5");  
    #endregion  
  
    //Add the defined action to the cube  
    cube.Actions.Add(rsaction);  
  
    #endregion  
}  

Obiekty kluczowego wskaźnika wydajności

Kluczowym wskaźnikiem wydajności (KPI) jest kolekcja obliczeń skojarzonych z grupą miar w module i służy do oceny sukcesu biznesowego. Kpi obiekty mogą być definiowane przez aplikację AMO, ale są używane z poziomu aplikacji klienckiej, która przegląda dane.

Kpi Utworzenie obiektu wymaga następujących kroków:

  1. Kpi Utwórz obiekt i wypełnij podstawowe atrybuty.

    Poniżej znajduje się lista podstawowych atrybutów: Opis, Folder wyświetlania, Skojarzona grupa miar i Wartość. Folder wyświetlania informuje aplikację kliencką, w którym powinien znajdować się kluczowy wskaźnik wydajności dla użytkownika końcowego. Skojarzona grupa miar wskazuje grupę miar, w której należy odwoływać się do wszystkich obliczeń MDX. Wartość przedstawia rzeczywistą wartość wskaźnika wydajności jako wyrażenie MDX.

  2. Definiowanie wskaźników KPI: cel, stan i trend.

    Wskaźniki to wyrażenia MDX, które powinny być obliczane w przedziale od -1 do 1, ale aplikacja przeglądania definiuje zakres wartości dla tych wskaźników.

  3. Podczas przeglądania kluczowych wskaźników wydajności wartości mniejsze niż -1 są traktowane jako -1, a wartości większe niż 1 są traktowane jako 1.

  4. Zdefiniuj obrazy graficzne.

    Obrazy graficzne to wartości ciągów używane jako odwołanie w aplikacji klienckiej do identyfikowania poprawnego zestawu obrazów do wyświetlenia. Ciąg obrazu graficznego definiuje również zachowanie funkcji wyświetlania. Zazwyczaj zakres jest podzielony na nieparzystą liczbę stanów, od złego do dobrego, a do każdego stanu przypisywany jest obraz z zestawu.

    Jeśli używasz programu Visual Studio do przeglądania wskaźników KPI, w zależności od nazw zakres wskaźników jest podzielony na trzy stany lub pięć stanów. Ponadto istnieją nazwy, w których zakres jest odwrócony, czyli -1 jest "Dobry", a 1 to "Bad". W programie Visual Studio trzy stany w tym zakresie są następujące:

    • Bad = -1 do -0,5

    • OK = -0,4999 do -0,4999

    • Dobry = od 0,50 do 1

    W programie Visual Studio pięć stanów w zakresie jest następujących:

    • Bad = od -1 do -0,75

    • Ryzyko = -0,7499 do -0,25

    • OK = -0,2499 do 0,2499

    • Podnoszenie = 0,25 do 0,7499

    • Dobre = od 0,75 do 1

Poniższa tabela zawiera listę stanów użycia, nazwy i liczby stanów skojarzonych z obrazem.

Użycie obrazu Nazwa obrazu Liczba stanów
Status Shapes 3
Status Sygnalizacja świetlna 3
Status Znaki drogowe 3
Status Miernik 3
Status Odwrócony miernik 5
Status Termometr 3
Status Cylindr 3
Status Faces 3
Status Strzałka wariancji 3
Tendencja Strzałka standardowa 3
Tendencja Strzałka stanu 3
Tendencja Odwrócona strzałka statusu 5
Tendencja Faces 3
  1. Dodaj wskaźnik KPI do kolekcji kostek i zaktualizuj kostkę, ponieważ wskaźnik KPI nie jest obiektem, który można zaktualizować.

Testowanie kluczowego wskaźnika wydajności wymaga innej aplikacji programowej. Wskaźnik KPI można przetestować w programie Visual Studio.

Poniższy przykładowy kod tworzy KPI w folderze "Financial Perspective/Grow Revenue" dla kostki Adventure Works uwzględnionej w przykładzie projektu Adventure Works Analysis Services.

static public void CreateKPIs(Cube cube)  
{  
    Kpi kpi = cube.Kpis.Add("My Internet Revenue", "My Internet Revenue");  
    kpi.Description = "(My) Revenue achieved through direct sales via Interner";  
    kpi.DisplayFolder = "\\Financial Perspective\\Grow Revenue";  
    kpi.AssociatedMeasureGroupID = "Internet Sales";  
    kpi.Value = "[Measures].[Internet Sales Amount]";  
    #region Goal  
    kpi.Goal = "Case" +  
               "     When IsEmpty" +  
               "          (" +  
               "            ParallelPeriod" +  
               "            (" +  
               "              [Date].[Fiscal Time].[Fiscal Year]," +  
               "              1," +  
               "              [Date].[Fiscal Time].CurrentMember" +  
               "            )" +  
               "          )" +   
               "     Then [Measures].[Internet Sales Amount]" +  
               "     Else 1.10 *" +  
               "          (" +  
               "            [Measures].[Internet Sales Amount]," +  
               "            ParallelPeriod" +  
               "            (" +  
               "              [Date].[Fiscal Time].[Fiscal Year]," +  
               "              1," +  
               "              [Date].[Fiscal Time].CurrentMember" +  
               "            )" +  
               "          ) " +  
               " End";  
    #endregion  
    #region Status  
    kpi.Status = "Case" +  
                 "   When KpiValue( \"Internet Revenue\" ) / KpiGoal ( \"Internet Revenue\" ) >= .95 " +  
                 "   Then 1 " +  
                 "   When KpiValue( \"Internet Revenue\" ) / KpiGoal ( \"Internet Revenue\" ) <  .95 " +  
                 "        And  " +  
                 "        KpiValue( \"Internet Revenue\" ) / KpiGoal ( \"Internet Revenue\" ) >= .85 " +  
                 "   Then 0 " +  
                 "   Else -1 " +  
                 "End";  
    #endregion  
    #region Trend  
    kpi.Trend = "Case " +  
                "    When VBA!Abs " +  
                "         ( " +  
                "           KpiValue( \"Internet Revenue\" ) -  " +  
                "           ( " +  
                "             KpiValue ( \"Internet Revenue\" ), " +  
                "             ParallelPeriod " +  
                "             (  " +  
                "               [Date].[Fiscal Time].[Fiscal Year], " +  
                "               1, " +  
                "               [Date].[Fiscal Time].CurrentMember " +  
                "             ) " +  
                "           ) / " +  
                "           ( " +  
                "             KpiValue ( \"Internet Revenue\" ), " +  
                "             ParallelPeriod " +  
                "             (  " +  
                "               [Date].[Fiscal Time].[Fiscal Year], " +  
                "               1, " +  
                "               [Date].[Fiscal Time].CurrentMember " +  
                "             ) " +  
                "           )   " +  
                "         ) <=.02  " +  
                "    Then 0 " +  
                "    When KpiValue( \"Internet Revenue\" ) -  " +  
                "         ( " +  
                "           KpiValue ( \"Internet Revenue\" ), " +  
                "           ParallelPeriod " +  
                "           (  " +  
                "             [Date].[Fiscal Time].[Fiscal Year], " +  
                "             1, " +  
                "             [Date].[Fiscal Time].CurrentMember " +  
                "           ) " +  
                "         ) / " +  
                "         ( " +  
                "           KpiValue ( \"Internet Revenue\" ), " +  
                "           ParallelPeriod " +  
                "           (  " +  
                "             [Date].[Fiscal Time].[Fiscal Year], " +  
                "             1, " +  
                "             [Date].[Fiscal Time].CurrentMember " +  
                "           ) " +  
                "         )  >.02 " +  
                "    Then 1 " +  
                "    Else -1 " +  
                "End";  
    #endregion  
    kpi.TrendGraphic = "Standard Arrow";  
    kpi.StatusGraphic = "Cylinder";  
}.  

Obiekty perspektywy

Perspective obiekty mogą być definiowane przez aplikację AMO, ale są używane z poziomu aplikacji klienckiej, która przegląda dane.

Perspective Utworzenie obiektu wymaga następujących kroków:

  1. Perspective Utwórz obiekt i wypełnij podstawowe atrybuty.

    Poniżej znajduje się lista podstawowych atrybutów: Nazwa, Miara domyślna, Opis i adnotacje.

  2. Dodaj wszystkie obiekty z modułu nadrzędnego, które powinny być widoczne dla użytkownika końcowego.

    Dodaj wymiary kostki (atrybuty i hierarchie), grupy miar (miary i grupa miar), akcje, kluczowe wskaźniki wydajności (KPI) i obliczenia.

  3. Dodaj perspektywę do kolekcji modułów i zaktualizuj moduł, ponieważ perspektywa nie jest obiektem aktualizowalnym.

Testowanie perspektywy wymaga innej aplikacji programowej.

Poniższy przykładowy kod tworzy perspektywę o nazwie "Sprzedaż bezpośrednia" dla dostarczonego modułu.

static public void CreatePerspectives(Cube cube)  
{  
    Perspective perspective = cube.Perspectives.Add("Direct Sales", "Direct Sales");  
    CubeDimension dim1 = cube.Dimensions.GetByName("Date");  
    PerspectiveDimension pdim1 = perspective.Dimensions.Add(dim1.DimensionID);  
    pdim1.Attributes.Add("Date");  
    pdim1.Attributes.Add("Calendar Year");  
    pdim1.Attributes.Add("Fiscal Year");  
    pdim1.Attributes.Add("Calendar Quarter");  
    pdim1.Attributes.Add("Fiscal Quarter");  
    pdim1.Attributes.Add("Calendar Month Number");  
    pdim1.Attributes.Add("Fiscal Month Number");  
    pdim1.Hierarchies.Add("Calendar Time");  
    pdim1.Hierarchies.Add("Fiscal Time");  
  
    CubeDimension dim2 = cube.Dimensions.GetByName("Product");  
    PerspectiveDimension pdim2 = perspective.Dimensions.Add(dim2.DimensionID);  
    pdim2.Attributes.Add("Product Name");  
    pdim2.Attributes.Add("Product Line");  
    pdim2.Attributes.Add("Model Name");  
    pdim2.Attributes.Add("List Price");  
    pdim2.Attributes.Add("Size");  
    pdim2.Attributes.Add("Weight");  
    pdim2.Hierarchies.Add("Product Model Categories");  
    pdim2.Hierarchies.Add("Product Categories");  
  
    PerspectiveMeasureGroup pmg = perspective.MeasureGroups.Add("Internet Sales");  
    pmg.Measures.Add("Internet Sales Amount");  
    pmg.Measures.Add("Internet Order Quantity");  
    pmg.Measures.Add("Internet Unit Price");  
  
    pmg = perspective.MeasureGroups.Add("Reseller Sales");  
    pmg.Measures.Add("Reseler Sales Amount");  
    pmg.Measures.Add("Reseller Order Quantity");  
    pmg.Measures.Add("Reseller Unit Price");  
  
    PerspectiveAction pact = perspective.Actions.Add("Drillthrough Action");  
  
    PerspectiveKpi pkpi = perspective.Kpis.Add("Internet Revenue");  
    Cube.Update();  
}  

Obiekty Proaktywnecaching

ProactiveCaching obiekty mogą być definiowane przez AMO.

ProactiveCaching Utworzenie obiektu wymaga następujących kroków:

  1. ProactiveCaching Utwórz obiekt.

    Nie ma podstawowych atrybutów do zdefiniowania.

  2. Dodaj specyfikacje pamięci podręcznej.

Specification Description
AgregacjaStorage Typ magazynu dla agregacji.

Dotyczy tylko partycji. Wymiar musi być Regularny.
InterwałCiszy Minimalny czas istnienia pamięci podręcznej przed rozpoczęciem tworzenia obrazu MOLAP.
Opóźnienie Czas między najwcześniejszym powiadomieniem a momentem zniszczenia obrazów MOLAP.
InterwałNadpisaniaCiszy Czas po początkowym powiadomieniu, po którym przetwarzanie obrazów MOLAP rozpoczyna się bezwarunkowo.
ForceRebuildInterval Czas po tym, jak zostanie wygenerowany nowy obraz MOLAP, po którym proces obrazowania MOLAP rozpoczyna się bezwarunkowo (bez powiadomień).
Onlinemode Gdy obraz MOLAP jest dostępny.

Może to być Natychmiastowe lub OnCacheComplete.
  1. ProactiveCaching Dodaj obiekt do kolekcji nadrzędnej. Należy zaktualizować obiekt nadrzędny, ponieważ ProactiveCaching nie jest aktualizowalnym obiektem.

Poniższy przykładowy kod tworzy ProactiveCaching obiekt we wszystkich partycjach z grupy miary Internet Sales w module Adventure Works w określonej bazie danych.

static public void SetProactiveCachingSettings(Database db)  
{  
    ProactiveCaching pc;  
    if (db.Cubes.ContainsName("Adventure Works") && db.Cubes.FindByName("Adventure Works").MeasureGroups.ContainsName("Internet Sales"))  
    {  
        ProactiveCachingTablesBinding pctb;  
        TableNotification tn;  
  
        MeasureGroup mg = db.Cubes.FindByName("Adventure Works").MeasureGroups.FindByName("Internet Sales");  
        foreach(Partition part in mg.Partitions)  
        {  
            pc = new ProactiveCaching();  
            pc.AggregationStorage = ProactiveCachingAggregationStorage.MolapOnly;  
            pc.SilenceInterval = TimeSpan.FromSeconds(10);  
            pc.Latency = TimeSpan.FromSeconds(-1);  
            pc.SilenceOverrideInterval = TimeSpan.FromMinutes(10);  
            pc.ForceRebuildInterval = TimeSpan.FromSeconds(-1);  
            pc.Enabled = true;  
            pc.OnlineMode = ProactiveCachingOnlineMode.OnCacheComplete;  
            pctb = new ProactiveCachingTablesBinding();  
            pctb.NotificationTechnique = NotificationTechnique.Server;  
            tn = new TableNotification("[FactInternetSales]", "dbo");  
            pctb.TableNotifications.Add( tn);  
            pc.Source = pctb;  
  
            part.ProactiveCaching = pc;  
            part.Update();  
        }  
    }  
}  

Obiekty translacji

Obiekty tłumaczenia mogą być definiowane przez aplikację AMO, ale są używane z aplikacji klienckiej, która przegląda dane. Obiekty translacji są prostymi obiektami kodu. Tłumaczenia podpisów obiektów są dostarczane przez pary identyfikatora ustawień regionalnych i przetłumaczony podpis. W przypadku dowolnego napisu można włączyć wiele tłumaczeń. Tłumaczenia mogą być udostępniane dla większości obiektów, takich jak wymiary, atrybuty, hierarchie, moduły, grupy miar, miary i inne.

Poniższy przykładowy kod zawiera hiszpańskie tłumaczenie nazwy atrybutu Nazwa produktu.

static public void CreateTranslations(Database db)  
{  
    //Spanish Tranlations for Product Category in Product Dimension  
    Dimension dim = db.Dimensions["Product"];  
    DimensionAttribute atr = dim.Attributes["Product Name"];  
    Translation tran = atr.Translations.Add(3082);  
    tran.Caption = "Nombre Producto";  
  
    dim.Update(UpdateOptions.ExpandFull);  
  
}