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


Программирование базовых объектов AMO OLAP

Применимо к: SQL Server Analysis Services Azure Analysis Services Fabric/Power BI Premium

Создание сложных объектов служб Analysis Services является простым и простым, но требует внимания к деталям. В этом разделе подробно описывается программирование базовых объектов OLAP. Этот раздел состоит из следующих подразделов.

Объекты класса Dimension

Для администрирования или обработки измерения необходимо запрограммировать Dimension объект .

Создание, удаление и поиск измерения

Создание Dimension объекта выполняется в четыре этапа:

  1. Создайте объект измерения и заполните основные атрибуты.

    Основными атрибутами являются: «Имя», «Тип измерения», «Режим хранения», «Привязка к источнику данных», «Имя элемента "Все" атрибута» и другие атрибуты измерения.

    Перед созданием измерения необходимо удостоверится, что такое измерение не существует. Если измерение существует, то оно будет удалено и создано повторно.

  2. Создайте атрибуты, определяющие измерение.

    Перед его использованием каждый атрибут необходимо добавить в схему отдельно (метод CreateDataItem приведен в конце образца кода), а затем его можно будет добавить в коллекцию атрибутов измерения.

    Столбцы «Key» и «Name» должны быть определены во всех атрибутах.

    Первичный ключевой атрибут измерения следует определять как AttributeUsage.Key, чтобы было ясно, что этот атрибут является ключом доступа к измерению.

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

    При создании иерархий порядок уровней определяется порядком, в котором сверху вниз создаются уровни. Верхним уровнем является добавленный первым в коллекцию уровней иерархии.

  4. Обновите сервер при помощи метода Update текущего измерения.

В следующем примере кода создается измерение Product из таблицы Продуктов Adventure Works в образце базы данных.

static void CreateProductDimension(Database db, string datasourceName)  
{  
    // Create the Product dimension  
    Dimension dim = db.Dimensions.FindByName("Product");  
    if ( dim != null)  
       dim.Drop();  
    dim = db.Dimensions.Add("Product");  
    dim.Type = DimensionType.Products;  
    dim.UnknownMember = UnknownMemberBehavior.Hidden;  
    dim.AttributeAllMemberName = "All Products";  
    dim.Source = new DataSourceViewBinding(datasourceName);  
    dim.StorageMode = DimensionStorageMode.Molap;  
  
    #region Create attributes  
  
    DimensionAttribute attr;  
  
    attr = dim.Attributes.Add("Product Name");  
    attr.Usage = AttributeUsage.Key;  
    attr.Type = AttributeType.Product;  
    attr.OrderBy = OrderBy.Name;  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "ProductKey"));  
    attr.NameColumn = CreateDataItem(db.DataSourceViews[0], "DimProduct", "EnglishProductName");  
  
    attr = dim.Attributes.Add("Product Line");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "ProductLine"));  
    attr.NameColumn = CreateDataItem(db.DataSourceViews[0], "DimProduct", "ProductLineName");  
  
    attr = dim.Attributes.Add("Model Name");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "ModelName"));  
    attr.AttributeRelationships.Add(new AttributeRelationship("Product Line"));  
    attr.AttributeRelationships.Add(new AttributeRelationship("Subcategory"));  
  
    attr = dim.Attributes.Add("Subcategory");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProductSubcategory", "ProductSubcategoryKey"));  
    attr.KeyColumns[0].NullProcessing = NullProcessing.UnknownMember;  
    attr.NameColumn = CreateDataItem(db.DataSourceViews[0], "DimProductSubcategory", "EnglishProductSubcategoryName");  
    attr.AttributeRelationships.Add(new AttributeRelationship("Category"));  
  
    attr = dim.Attributes.Add("Category");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProductCategory", "ProductCategoryKey"));  
    attr.NameColumn = CreateDataItem(db.DataSourceViews[0], "DimProductCategory", "EnglishProductCategoryName");  
  
    attr = dim.Attributes.Add("List Price");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "ListPrice"));  
    attr.AttributeHierarchyEnabled = false;  
  
    attr = dim.Attributes.Add("Size");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "Size"));  
    attr.AttributeHierarchyEnabled = false;  
  
    attr = dim.Attributes.Add("Weight");  
    attr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "DimProduct", "Weight"));  
    attr.AttributeHierarchyEnabled = false;  
  
    #endregion  
  
    #region Create hierarchies  
  
    Hierarchy hier;  
  
    hier = dim.Hierarchies.Add("Product Model Categories");  
    hier.AllMemberName = "All Products";  
    hier.Levels.Add("Category").SourceAttributeID = "Category";  
    hier.Levels.Add("Subcategory").SourceAttributeID = "Subcategory";  
    hier.Levels.Add("Model Name").SourceAttributeID = "Model Name";  
  
    hier = dim.Hierarchies.Add("Product Categories");  
    hier.AllMemberName = "All Products";  
    hier.Levels.Add("Category").SourceAttributeID = "Category";  
    hier.Levels.Add("Subcategory").SourceAttributeID = "Subcategory";  
    hier.Levels.Add("Model Name").SourceAttributeID = "Product Name";  
  
    hier = dim.Hierarchies.Add("Product Model Lines");  
    hier.AllMemberName = "All Products";  
    hier.Levels.Add("Subcategory").SourceAttributeID = "Product Line";  
    hier.Levels.Add("Model Name").SourceAttributeID = "Model Name";  
  
    #endregion  
  
    dim.Update();  
}  
  
static DataItem CreateDataItem(DataSourceView dsv, string tableName, string columnName)  
{  
    DataTable dataTable = ((DataSourceView)dsv).Schema.Tables[tableName];  
    DataColumn dataColumn = dataTable.Columns[columnName];  
    return new DataItem(tableName, columnName,  
        OleDbTypeConverter.GetRestrictedOleDbType(dataColumn.DataType));  
}  
  

Обработка измерения

Обработка измерения выполняется так же просто, как и с помощью метода Dimension Process объекта .

Обработка измерения может затронуть все кубы, использующие это измерение.

В следующем коде выполняется добавочное обновление во всех измерениях указанной базы данных:

static void UpdateAllDimensions(Database db)  
{  
    foreach (Dimension dim in db.Dimensions)  
        dim.Process(ProcessType.ProcessUpdate);  
}  

Объекты класса Cube

Для администрирования или обработки куба необходимо запрограммировать Cube объект .

Создание, удаление и поиск куба

Управление кубами осуществляется так же, как управление измерениями. Создание Cube объекта выполняется в четыре этапа:

  1. Создайте объект куба и заполните основные атрибуты.

    Основными атрибутами являются «Имя», «Режим хранения», «Привязка к источнику данных», «Мера по умолчанию» и другие атрибуты куба.

    Перед созданием куба следует удостовериться, что такой куб не существует. В данном образце, если куб существует, то будет удален, а затем снова создан.

  2. Добавление измерений куба.

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

    Обратите внимание, что в образце кода измерение «Date» добавляется три раза и при каждом добавлении используется другое имя измерения куба: «Date», «Ship Date», «Delivery Date». Эти измерения называются "ролевой игрой". Базовое измерение совпадает (Дата), но в таблице фактов это измерение используется в разных "ролях" (Дата заказа, Дата отправки, Дата доставки). См. раздел "Создание, удаление и поиск Группы мер" далее в этом документе, чтобы понять, как определяются "ролевые" измерения.

  3. Создайте группы мер, доступ к которым будет получать пользователь, чтобы просматривать данные куба.

    Создание группы мер описывается в разделе «Создание, удаление и поиск группы мер» ниже в этом документе. В этом образце в качестве оболочки для процесса создания группы мер применяются разные методы, по одному на каждую группу мер.

  4. Обновите сервер при помощи метода Update текущего куба.

    Метод обновления используется с параметром обновления ExpandFull, что позволяет гарантировать полное обновление всех объектов на сервере.

В следующем образце кода создаются части куба Adventure Works. В этом образце кода не создаются все измерения или группы мер, включенные в образец проекта служб Adventure Works Analysis Services.

static void CreateAdventureWorksCube(Database db, string datasourceName)  
{  
    // Create the Adventure Works cube  
    Cube cube = db.Cubes.FindByName("Adventure Works");  
    if ( cube != null)  
       cube.Drop();  
    db.Cubes.Add("Adventure Works");  
    cube.DefaultMeasure = "[Reseller Sales Amount]";  
    cube.Source = new DataSourceViewBinding(datasourceName);  
    cube.StorageMode = StorageMode.Molap;  
  
    #region Create cube dimensions  
  
    Dimension dim;  
  
    dim = db.Dimensions.GetByName("Date");  
    cube.Dimensions.Add(dim.ID, "Date", "Order Date Key - Dim Time");  
    cube.Dimensions.Add(dim.ID, "Ship Date",  
        "Ship Date Key - Dim Time");  
    cube.Dimensions.Add(dim.ID, "Delivery Date",  
        "Delivery Date Key - Dim Time");  
  
    dim = db.Dimensions.GetByName("Customer");  
    cube.Dimensions.Add(dim.ID);  
  
    dim = db.Dimensions.GetByName("Reseller");  
    cube.Dimensions.Add(dim.ID);  
    #endregion  
  
    #region Create measure groups  
  
    CreateSalesReasonsMeasureGroup(cube);  
    CreateInternetSalesMeasureGroup(cube);  
    CreateResellerSalesMeasureGroup(cube);  
    CreateCustomersMeasureGroup(cube);  
    CreateCurrencyRatesMeasureGroup(cube);  
  
    #endregion  
  
    cube.Update(UpdateOptions.ExpandFull);  
}  

Обработка куба

Обработка куба выполняется так же просто, как и с помощью метода Cube Process объекта . При обработке куба обрабатываются все группы мер в этом кубе, а также все секции в группах мер. В кубе единственными объектами, которые можно обработать, являются секции; группы мер с точки зрения обработки представляют собой всего лишь контейнеры секций. Выбранный для куба тип обработки распространяется и на его секции. Обработка куба и группы мер по существу сводится к обработке измерений и секций.

В следующем коде выполняется полная обработка всех кубов в указанной базе данных:

foreach (Cube cube in db.Cubes)  
             cube.Process(ProcessType.ProcessFull);  
     }  

Объекты MeasureGroup

Для администрирования или обработки группы мер необходимо запрограммировать MeasureGroup объект .

Создание, удаление и поиск MeasureGroup

Управление группами мер осуществляется так же, как управление измерениями и кубами. Создание MeasureGroup объекта выполняется в следующих шагах:

  1. Создайте объект группы мер и заполните основные атрибуты.

    Основными атрибутами являются «Имя», «Режим хранения», «Режим обработки», «Мера по умолчанию» и другие атрибуты группы мер.

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

  2. Создайте меры группы мер. Каждой создаваемой группе мер назначаются следующие атрибуты: имя, статистическая функция, исходный столбец, строка форматирования. Могут быть назначены и другие атрибуты. Обратите внимание, что в приведенном ниже образце кода метод CreateDataItem добавляет столбец в схему.

  3. Добавление измерений группы мер.

  4. Измерения добавляются в текущую коллекцию измерений группы мер из коллекции измерений родительского куба. Как только измерение будет включено в коллекцию измерений группы мер, ключевой столбец из таблицы фактов можно будет сопоставить с этим измерением, чтобы данную группу мер можно было просматривать через это измерение.

    В приведенном далее образце кода см. строки под заголовком «Mapping dimension and key column from fact table». Ролевые измерения реализуются путем связывания разных суррогатных ключей с одним измерением под разными именами. С каждым из ролевых измерений («Date», «Ship Date», «Delivery Date») связывается отдельный суррогатный ключ (OrderDateKey, ShipDateKey, DueDateKey). Все ключи берутся из таблицы фактов FactInternetSales.

  5. Добавление спроектированных секций группы мер.

    В приведенном далее образце кода в качестве оболочки для процесса создания секции применяется один метод.

  6. Обновите сервер при помощи метода Update текущей группы мер.

    В приведенном далее образце кода все группы мер обновляются при обновлении куба.

В следующем образце кода создастся группа мер InternetSales образца проекта служб Adventure Works Analysis Services.

static void CreateInternetSalesMeasureGroup(Cube cube)  
{  
    // Create the Internet Sales measure group  
    Database db = cube.Parent;  
    MeasureGroup mg = cube.MeasureGroups.FindByName("Internet Sales");  
    if ( mg != null)  
       mg.Drop();  
    mg = cube.MeasureGroups.Add("Internet Sales");  
    mg.StorageMode = StorageMode.Molap;  
    mg.ProcessingMode = ProcessingMode.LazyAggregations;  
    mg.Type = MeasureGroupType.Sales;  
  
    #region Create measures  
  
    Measure meas;  
  
    meas = mg.Measures.Add("Internet Sales Amount");  
    meas.AggregateFunction = AggregationFunction.Sum;  
    meas.FormatString = "Currency";  
    meas.Source = CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "SalesAmount");  
  
    meas = mg.Measures.Add("Internet Order Quantity");  
    meas.AggregateFunction = AggregationFunction.Sum;  
    meas.FormatString = "#,#";  
    meas.Source = CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "OrderQuantity");  
  
    meas = mg.Measures.Add("Internet Unit Price");  
    meas.AggregateFunction = AggregationFunction.Sum;  
    meas.FormatString = "Currency";  
    meas.Visible = false;  
    meas.Source = CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "UnitPrice");  
  
    meas = mg.Measures.Add("Internet Total Product Cost");  
    meas.AggregateFunction = AggregationFunction.Sum;  
    //meas.MeasureExpression = "[Internet Total Product Cost] * [Average Rate]";  
    meas.FormatString = "Currency";  
    meas.Source = CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "TotalProductCost");  
  
    meas = mg.Measures.Add("Internet Order Count");  
    meas.AggregateFunction = AggregationFunction.Count;  
    meas.FormatString = "#,#";  
    meas.Source = CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "ProductKey");  
  
    #endregion  
  
    #region Create measure group dimensions  
  
    CubeDimension cubeDim;  
    RegularMeasureGroupDimension regMgDim;  
    ManyToManyMeasureGroupDimension mmMgDim;  
    MeasureGroupAttribute mgAttr;  
  
    //   Mapping dimension and key column from fact table  
    //      > select dimension and add it to the measure group  
    cubeDim = cube.Dimensions.GetByName("Date");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
  
    //      > add key column from dimension and map it with   
    //        the surrogate key in the fact table  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Date").ID);   // this is dimension key column  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "OrderDateKey"));   // this surrogate key in fact table  
  
    cubeDim = cube.Dimensions.GetByName("Ship Date");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Date").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "ShipDateKey"));  
  
    cubeDim = cube.Dimensions.GetByName("Delivery Date");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Date").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "DueDateKey"));  
  
    cubeDim = cube.Dimensions.GetByName("Customer");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Full Name").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "CustomerKey"));  
  
    cubeDim = cube.Dimensions.GetByName("Product");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Product Name").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "ProductKey"));  
  
    cubeDim = cube.Dimensions.GetByName("Source Currency");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Currency").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "CurrencyKey"));  
  
    cubeDim = cube.Dimensions.GetByName("Sales Reason");  
    mmMgDim = new ManyToManyMeasureGroupDimension();  
    mmMgDim.CubeDimensionID = cubeDim.ID;  
    mmMgDim.MeasureGroupID = cube.MeasureGroups.GetByName("Sales Reasons").ID;  
    mg.Dimensions.Add(mmMgDim);  
  
    cubeDim = cube.Dimensions.GetByName("Internet Sales Order Details");  
    regMgDim = new RegularMeasureGroupDimension(cubeDim.ID);  
    mg.Dimensions.Add(regMgDim);  
    mgAttr = regMgDim.Attributes.Add(cubeDim.Dimension.Attributes.GetByName("Sales Order Key").ID);  
    mgAttr.Type = MeasureGroupAttributeType.Granularity;  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "SalesOrderNumber"));  
    mgAttr.KeyColumns.Add(CreateDataItem(db.DataSourceViews[0], "FactInternetSales", "SalesOrderLineNumber"));  
  
    #endregion  
  
    #region Create partitions  
  
    CreateInternetSalesMeasureGroupPartitions( mg)  
  
    #endregion  
}  

Обработка группы мер

Обработка группы мер выполняется так же просто, как и с помощью метода MeasureGroup Process объекта . При отработке группы мер будут также обработаны и все секции, принадлежащие к ней. Внутри группы мер ее обработка сводится к обработке измерений и секций. См. раздел Обработка секции в этом документе.

В следующем коде выполняется полная обработка всех групп мер указанного куба.

static void FullProcessAllMeasureGroups(Cube cube)  
{  
    foreach (MeasureGroup mg in cube.MeasureGroups)  
        mg.Process(ProcessType.ProcessFull);  
}  

Объекты секционирования

Для администрирования или обработки секции необходимо запрограммировать Partition объект .

Создание, удаление и поиск секции

Секции — это простые объекты, которые можно создать за два шага.

  1. Создайте объект секции и заполните его основные атрибуты.

    Основными атрибутами являются «Имя», «Режим хранения», «Источник секции», «Срез», а также другие атрибуты группы мер. Атрибут «Источник секции» определяет инструкцию выборки SQL для текущей секции. Срез — это многомерное выражение, указывающее кортеж или набор, который разграничивает часть измерений, которые содержатся в текущей секции, от родительской группы мер. Для секций MOLAP срезы определяются автоматически при каждой обработке секции.

    Перед созданием секции следует удостовериться, что такая секция не существует. В приведенном ниже образце кода предусмотрено, что если секция существует, то будет удалена и создана повторно.

  2. Обновите сервер при помощи метода Update текущей секции.

    В приведенном далее образце кода все секции обновляются при обновлении куба.

В приведенном ниже образце кода создаются секции для группы мер «InternetSales».

static void CreateInternetSalesMeasureGroupPartitions(MeasureGroup mg)  
{  
    Partition part;  
    part = mg.Partitions.FindByName("Internet_Sales_184");  
    if ( part != null)  
       part.Drop();  
    part = mg.Partitions.Add("Internet_Sales_184");  
    part.StorageMode = StorageMode.Molap;  
    part.Source = new QueryBinding(db.DataSources[0].ID, "SELECT * FROM [dbo].[FactInternetSales] WHERE OrderDateKey <= '184'");  
    part.Slice = "[Date].[Calendar Year].&[2001]";  
    part.Annotations.Add("LastOrderDateKey", "184");  
  
    part = mg.Partitions.FindByName("Internet_Sales_549");  
    if ( part != null)  
       part.Drop();  
    part = mg.Partitions.Add("Internet_Sales_549");  
    part.StorageMode = StorageMode.Molap;  
    part.Source = new QueryBinding(db.DataSources[0].ID, "SELECT * FROM [dbo].[FactInternetSales] WHERE OrderDateKey > '184' AND OrderDateKey <= '549'");  
    part.Slice = "[Date].[Calendar Year].&[2002]";  
    part.Annotations.Add("LastOrderDateKey", "549");  
  
    part = mg.Partitions.FindByName("Internet_Sales_914");  
    if ( part != null)  
       part.Drop();  
    part = mg.Partitions.Add("Internet_Sales_914");  
    part.StorageMode = StorageMode.Molap;  
    part.Source = new QueryBinding(db.DataSources[0].ID, "SELECT * FROM [dbo].[FactInternetSales] WHERE OrderDateKey > '549' AND OrderDateKey <= '914'");  
    part.Slice = "[Date].[Calendar Year].&[2003]";  
    part.Annotations.Add("LastOrderDateKey", "914");  
}  

Обработка секции

Обработка секции так же проста, как и с помощью метода Partition Process объекта .

В следующем образце кода выполняется полная обработка во всех секциях указанной группы мер.

static void FullProcessAllPartitions(MeasureGroup mg)  
{  
    foreach (Partition part in mg.Partitions)  
        part.Process(ProcessType.ProcessFull);  
}  

Слияние секций

Слияние секций означает выполнение любых операций, в результате которых две или большее количество секций становятся одной.

Объединение секций является методом Partition объекта . Эта команда выполняет слияние данных из одной или нескольких исходных секций в целевую секцию, а затем удаляет исходные секции.

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

  • Секции находятся в одной и той же группе мер.

  • Секции хранятся в одном и том же режиме (MOLAP, HOLAP или ROLAP).

  • Секции находятся на одном сервере; слияние дистанционно расположенных секций можно выполнить, если они находятся на одной сервере.

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

Итоговым набором агрегатов для целевой секции становится тот же набор агрегатов, который имелся перед выполнением команды слияния.

В следующем образце кода выполняется слияние всех секций указанной группы мер. Секции сливаются в первую секцию группы мер.

static void MergeAllPartitions(MeasureGroup mg)  
{  
    if (mg.Partitions.Count > 1)  
    {  
        Partition[] partArray = new Partition[mg.Partitions.Count - 1];  
        for (int i = 1; i < mg.Partitions.Count; i++)  
            partArray[i - 1] = mg.Partitions[i];  
        mg.Partitions[0].Merge(partArray);  
        //To have last changes in the server reflected in AMO  
        mg.Refresh();  
    }  

Объекты Aggregation

Чтобы спроектировать агрегат и применить его к одной или нескольким секциям, необходимо запрограммировать Aggregation объект .

Создание и удаление агрегатов

Агрегаты можно легко создавать и назначать группам мер или секциям с помощью метода DesignAggregations из AggregationDesign объекта . Объект AggregationDesign является отдельным от секции объектом, который AggregationDesign содержится в объекте MeasureGroup . Агрегаты можно проектировать с учетом достижения указанного уровня оптимизации (числа от 0 до 100) либо до указанного уровня хранения (байты). Одну и ту же статистическую схему можно использовать в нескольких секциях.

В следующем образце кода создаются агрегаты для всех секций указанной группы мер. Все существующие в секциях агрегаты удаляются.

static public String DesignAggregationsOnPartitions(MeasureGroup mg, double optimizationWanted, double maxStorageBytes)  
{  
    double optimization = 0;  
    double storage = 0;  
    long aggCount = 0;  
    bool finished = false;  
    AggregationDesign ad = null;  
    String aggDesignName;  
    String AggregationsDesigned = "";  
    aggDesignName = mg.AggregationPrefix + "_" + mg.Name;  
    ad = mg.AggregationDesigns.Add();  
    ad.Name = aggDesignName;  
    ad.InitializeDesign();  
    while ((!finished) && (optimization < optimizationWanted) && (storage < maxStorageBytes))  
    {  
        ad.DesignAggregations(out optimization, out storage, out aggCount, out finished);  
    }  
    ad.FinalizeDesign();  
    foreach (Partition part in mg.Partitions)  
    {  
        part.AggregationDesignID = ad.ID;  
        AggregationsDesigned += aggDesignName + " = " + aggCount.ToString() + " aggregations designed\r\n\tOptimization: " + optimization.ToString() + "/" + optimizationWanted.ToString() + "\n\r\tStorage: " + storage.ToString() + "/" + maxStorageBytes.ToString() + " ]\n\r";  
     }  
     return AggregationsDesigned;  
}