次の方法で共有


テーブル表現 (テーブル)

テーブル モデルでは、テーブルがデータの基本表現です。データは、行と列で構成された四角形のデータとして表されます。 すべての行が同じ数の図形または列を持ちます。

テーブル表現

テーブル オブジェクト モデルでは、テーブルは単純な論理オブジェクトです。つまり、同じ種類のレコード (行) のコレクションです。 それぞれの行が一定数の属性 (列) で構成されており、その各属性が単純なデータ型になっています。

AMO 内のテーブル

AMO を使用してテーブル モデル テーブルを管理する場合、AMO 内のテーブルに 1 対 1 で対応するオブジェクトは存在しません。AMO では、テーブルが Dimension および MeasureGroup によって表されます。 ただし、メジャー グループが存在するためには、そのメジャー グループをホストするために Cube を定義する必要があります。さらに、ディメンション、メジャー グループ、およびキューブが存在するためには、バインド定義をデータ ソースに格納するために、データ ソース ビュー オブジェクトを定義する必要があります。 まとめると、すべてのテーブルが存在するためには、共通のデータ ソース ビューとキューブが必要です。データ ソース ビューによって、論理テーブルを構成するディメンションとメジャー グループ内のデータ要素へのバインド (またはマッピング) が得られます。

実際の操作手順では、他のオブジェクトを定義する前にデータ ソース ビューを作成する必要があります。 データ ソース ビュー オブジェクトには、データ ソース内のすべての該当オブジェクトの、テーブル モデルに対するマッピングが含まれます。リレーショナル モデルのマッピングは、.NET DataSet オブジェクトとしてデータ ソース ビューに埋め込まれ、DSV の Schema プロパティに格納されます。

次のコード スニペットは、SQL クライアントの接続文字列、テーブル モデルで表現するリレーショナル モデルのすべてのテーブルにマップされる SELECT ステートメントのディクショナリ、データ ソース ビューの名前 (通常はリレーショナル データベースの名前) を持つ newDataSourceViewName 変数があることを想定しています。

  DataSet newDataSourceViewDataSet = new DataSet(newDataSourceViewName);

  Foreach( String tableName in listOfSqlStatements.Keys)
  {
      String sqlStmt = listOfSqlStatements[tableName];

      DataTable newTable = new DataTable(tableName);

      using (SqlConnection SqlCnx = new SqlConnection(SqlCnxStr))
      {
          SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlStmt, SqlCnx);
          dataAdapter.FillSchema(newTable, SchemaType.Source);
      }
      newDataSourceViewDataSet.Tables.Add(newTable);
  }

  AMO.DataSourceView newDatasourceView = newDatabase.DataSourceViews.AddNew(newDataSourceViewName, newDataSourceViewName);
  newDatasourceView.DataSourceID = newDatasource.ID; //This is the ID of the DataSource object 
  newDatasourceView.Schema = newDataSourceViewDataSet; //Here you are storing all the relational schema in the DSV
  newDatasourceView.Update();

データ ソース ビューが作成および更新されたらキューブ オブジェクトを作成する必要がありますが、最初のテーブルが作成されるまではサーバーで更新しないでください。 キューブ オブジェクトを空の状態で作成することはできません。 次のコード スニペットは、キューブの作成方法を示しています。このスニペットは、重複が検証済みのキューブ名を持つ、空ではない文字列 newCubeName があることも想定しています。

            modelCube = newDatabase.Cubes.Add(newCubeName, newCubeName);
            modelCube.Source = new AMO.DataSourceViewBinding(newDatasourceView.ID);
            modelCube.StorageMode = AMO.StorageMode.InMemory;
            modelCube.Language = newDatabase.Language;
            modelCube.Collation = newDatabase.Collation;
            //Create initial MdxScript
            AMO.MdxScript mdxScript = modelCube.MdxScripts.Add("MdxScript", "MdxScript");
            StringBuilder initialCommand = new StringBuilder();
            initialCommand.AppendLine("CALCULATE;");
            initialCommand.AppendLine("CREATE MEMBER CURRENTCUBE.Measures.[__No measures defined] AS 1;");
            initialCommand.AppendLine("ALTER CUBE CURRENTCUBE UPDATE DIMENSION Measures, Default_Member = [__No measures defined];");
            mdxScript.Commands.Add(new AMO.Command(initialCommand.ToString()));

キューブがローカルで定義されたら、テーブルを作成および更新できます。 次の手順で、テーブルの作成手順の概要を示します。

  1. テーブルを表すディメンションを作成します。まだサーバーは更新しないでください。

  2. RowNumber 属性を作成し、ディメンションのキー属性として定義します。

  3. ディメンション属性を作成し、RowNumber への一対多のリレーションシップでマークします。

  4. キューブ ディメンションにディメンションを追加します。

  5. テーブルも表すメジャー グループを作成します。

  6. メジャー グループにディメンションを追加します。

  7. メジャー グループに AMO の既定のメジャー オブジェクトを作成します。 AMO メジャー オブジェクトはここでしか使用しません。テーブル モデルの計算されるメジャーは、AMO MdxScripts["MdxScript"] オブジェクトで定義します。

  8. 既定のパーティションの作成

  9. データベースの更新

次のコード スニペットは、テーブルの作成方法を示しています。

        private Boolean CreateTable(
                               AMO.Database db      //the AMO database object where dimension are created
                             , AMO.Cube cb          //the AMO cube where measure group is created
                             , DataTable dataTable  //the schema of the table to be created
                             )
        {
            String tableID = dataTable.TableName;

            if (db.Dimensions.Contains(tableID))
            {
                if (cb.MeasureGroups.Contains(tableID))
                {
                    cb.MeasureGroups[tableID].Measures.Clear();
                    cb.MeasureGroups[tableID].Partitions.Clear();
                    cb.MeasureGroups.Remove(tableID, true);
                }
                if (cb.Dimensions.Contains(tableID))
                {
                    cb.Dimensions.Remove(tableID, true);
                }
                db.Dimensions.Remove(tableID);
            }

            #region Create Dimension
            //Define Dimension general properties
            AMO.Dimension currentDimension = db.Dimensions.AddNew(tableID, tableID);
            currentDimension.Source = new AMO.DataSourceViewBinding(newDatasourceView.ID);
            currentDimension.StorageMode = AMO.DimensionStorageMode.InMemory;
            currentDimension.UnknownMember = AMO.UnknownMemberBehavior.AutomaticNull;
            currentDimension.UnknownMemberName = "Unknown";
            currentDimension.ErrorConfiguration = new AMO.ErrorConfiguration();
            currentDimension.ErrorConfiguration.KeyNotFound = AMO.ErrorOption.IgnoreError;
            currentDimension.ErrorConfiguration.KeyDuplicate = AMO.ErrorOption.ReportAndStop;
            currentDimension.ErrorConfiguration.NullKeyNotAllowed = AMO.ErrorOption.ReportAndStop;
            currentDimension.Language = db.Language;
            currentDimension.Collation = db.Collation;
            currentDimension.ProactiveCaching = new AMO.ProactiveCaching();
            TimeSpan defaultProactiveChachingTimeSpan = new TimeSpan(0, 0, -1);
            currentDimension.ProactiveCaching.SilenceInterval = defaultProactiveChachingTimeSpan;
            currentDimension.ProactiveCaching.Latency = defaultProactiveChachingTimeSpan;
            currentDimension.ProactiveCaching.SilenceOverrideInterval = defaultProactiveChachingTimeSpan;
            currentDimension.ProactiveCaching.ForceRebuildInterval = defaultProactiveChachingTimeSpan;
            currentDimension.ProactiveCaching.Source = new AMO.ProactiveCachingInheritedBinding();

            //Manualy add a "RowNumber" attribute as the key attribute of the dimension, until a primary key is defined
            //"RowNumber" a required column for a tabular model and has to be of type AMO.AttributeType.RowNumber and binding AMO.RowNumberBinding
            //The name of the "RowNumber" attribute can be any name, as long as type and binding are correctly set
            //By default the MS client tools set the column name and column ID of the RowNumber attribute to "RowNumber"
            //In this sample, to avoid problems, on any customer table that contains a column named 'RowNumber' 
            //the Id value of the column (in the dimension object) will be renamed to 'RowNumber_in_<TableName>' and the Name of the column will remain "RowNumber"

            AMO.DimensionAttribute currentAttribute = currentDimension.Attributes.Add("RowNumber", "RowNumber");
            currentAttribute.Type = AMO.AttributeType.RowNumber;
            currentAttribute.KeyUniquenessGuarantee = true;
            currentAttribute.Usage = AMO.AttributeUsage.Key;
            currentAttribute.KeyColumns.Add(new AMO.DataItem());
            currentAttribute.KeyColumns[0].DataType = System.Data.OleDb.OleDbType.Integer;
            currentAttribute.KeyColumns[0].DataSize = 4;
            currentAttribute.KeyColumns[0].NullProcessing = AMO.NullProcessing.Error;
            currentAttribute.KeyColumns[0].Source = new AMO.RowNumberBinding();
            currentAttribute.NameColumn = new AMO.DataItem();
            currentAttribute.NameColumn.DataType = System.Data.OleDb.OleDbType.WChar;
            currentAttribute.NameColumn.DataSize = 4;
            currentAttribute.NameColumn.NullProcessing = AMO.NullProcessing.ZeroOrBlank;
            currentAttribute.NameColumn.Source = new AMO.RowNumberBinding();
            currentAttribute.OrderBy = AMO.OrderBy.Key;
            currentAttribute.AttributeHierarchyVisible = false;
            //Deferring AttributeRelationships until after adding each other attribute
            //Add each column in the table as an attribute in the dimension
            foreach (DataColumn dataColumn in dataTable.Columns)
            {
                string attributeID, attributeName;
                if (dataColumn.ColumnName != "RowNumber")
                {
                    attributeID = dataColumn.ColumnName;
                }
                else
                {
                    attributeID = string.Format("RowNumber_in_{0}", dataTable.TableName);
                }
                attributeName = dataColumn.ColumnName;
                currentAttribute = currentDimension.Attributes.Add(attributeName, attributeID);
                currentAttribute.Usage = AMO.AttributeUsage.Regular;
                currentAttribute.KeyUniquenessGuarantee = false;
                currentAttribute.KeyColumns.Add(new AMO.DataItem(dataTable.TableName, dataColumn.ColumnName, AMO.OleDbTypeConverter.GetRestrictedOleDbType(dataColumn.DataType)));
                currentAttribute.KeyColumns[0].Source = new AMO.ColumnBinding(dataTable.TableName, dataColumn.ColumnName);
                currentAttribute.KeyColumns[0].NullProcessing = AMO.NullProcessing.Preserve;
                currentAttribute.NameColumn = new AMO.DataItem(dataTable.TableName, dataColumn.ColumnName, System.Data.OleDb.OleDbType.WChar);
                currentAttribute.NameColumn.Source = new AMO.ColumnBinding(dataTable.TableName, dataColumn.ColumnName);
                currentAttribute.NameColumn.NullProcessing = AMO.NullProcessing.ZeroOrBlank;
                currentAttribute.OrderBy = AMO.OrderBy.Key;
                AMO.AttributeRelationship currentAttributeRelationship = currentDimension.Attributes["RowNumber"].AttributeRelationships.Add(currentAttribute.ID);
                currentAttributeRelationship.Cardinality = AMO.Cardinality.Many;
                currentAttributeRelationship.OverrideBehavior = AMO.OverrideBehavior.None;
            }
            #endregion

            #region Add Dimension to Model cube
            cb.Dimensions.Add(tableID, tableID, tableID);
            #endregion

            #region Add MeasureGroup to Model cube
            AMO.MeasureGroup currentMeasureGroup = cb.MeasureGroups.Add(tableID, tableID);
            currentMeasureGroup.StorageMode = AMO.StorageMode.InMemory;
            currentMeasureGroup.ProcessingMode = AMO.ProcessingMode.Regular;

            //Adding Dimension
            AMO.DegenerateMeasureGroupDimension currentMGDim = new AMO.DegenerateMeasureGroupDimension(tableID);
            currentMeasureGroup.Dimensions.Add(currentMGDim);
            currentMGDim.ShareDimensionStorage = AMO.StorageSharingMode.Shared;
            currentMGDim.CubeDimensionID = tableID;
            foreach (AMO.CubeAttribute ca in cb.Dimensions[tableID].Attributes)
            {
                AMO.MeasureGroupAttribute mga = new AMO.MeasureGroupAttribute(ca.AttributeID);
                if (mga.AttributeID == "RowNumber")
                {
                    mga.Type = AMO.MeasureGroupAttributeType.Granularity;
                    AMO.DataItem rowNumberKeyColumn = new AMO.DataItem(new AMO.ColumnBinding(tableID, "RowNumber"));
                    rowNumberKeyColumn.DataType = System.Data.OleDb.OleDbType.Integer;
                    mga.KeyColumns.Add(rowNumberKeyColumn);
                }
                else
                {
                    foreach (AMO.DataItem di in ca.Attribute.KeyColumns)
                    {
                        AMO.DataItem keyColumn = new AMO.DataItem(new AMO.ColumnBinding(tableID, ((AMO.ColumnBinding)di.Source).ColumnID));
                        keyColumn.DataType = di.DataType;
                        keyColumn.NullProcessing = AMO.NullProcessing.Preserve;
                        keyColumn.InvalidXmlCharacters = AMO.InvalidXmlCharacters.Remove;
                        mga.KeyColumns.Add(keyColumn);
                    }
                }
                currentMGDim.Attributes.Add(mga);
            }

            //Adding default Measure
            String defaultMeasureID = string.Concat("_Count ", tableID);
            AMO.Measure currentMeasure = currentMeasureGroup.Measures.Add(defaultMeasureID, defaultMeasureID);
            currentMeasure.AggregateFunction = AMO.AggregationFunction.Count;
            currentMeasure.DataType = AMO.MeasureDataType.BigInt;
            AMO.DataItem currentMeasureSource = new AMO.DataItem(new AMO.RowBinding(tableID));
            currentMeasureSource.DataType = System.Data.OleDb.OleDbType.BigInt;
            currentMeasure.Source = currentMeasureSource;

            //Partitions
            AMO.Partition currentPartition = new AMO.Partition(tableID, tableID);
            currentPartition.StorageMode = AMO.StorageMode.InMemory;
            currentPartition.ProcessingMode = AMO.ProcessingMode.Regular;
            currentPartition.Source = new AMO.QueryBinding(newDatasource.ID, (String)dataTable.ExtendedProperties["sqlStmt"]);
            currentMeasureGroup.Partitions.Add(currentPartition);

            #endregion

            #region Update new objects in database
            db.Update(AMO.UpdateOptions.ExpandFull, AMO.UpdateMode.UpdateOrCreate);
            #endregion

            return true;
        }
注記注意

上記のコード スニペットには、エラーが発生した際のエラー チェックやクリーンアップの手順は含まれていません。

AMO2Tabular サンプル

AMO を使用してデータベース表現の作成と操作を行う方法については、AMO to Tabular サンプルのソース コードを参照してください。特に、ソース ファイル "CreateTable.cs" の内容に注意してください。 このサンプルは、Codeplex でダウンロードできます。 このコードに関する重要な注意事項: このコードは、ここで説明する論理的概念を補足するためにのみ提供されています。運用環境では使用しないでください。教育目的以外の目的にも使用しないでください。