Representação de tabelas (de tabela)
Em modelos de tabela, uma tabela é a representação de base dos dados; dados são apresentados em um formato retangular de dados composto de linhas e colunas. Todas as linhas têm o mesmo formato ou colunas.
Representação de tabelas
Em modelos de objeto de tabela, a tabela é um objeto lógico simples: é uma coleção de registros (conhecidos como linhas) do mesmo tipo. Cada linha é composta de um número fixo de atributos (conhecidos como colunas), onde o tipo de dados de cada atributo é simples
Tabelas no AMO
Ao usar o AMO para gerenciar uma tabela de Modelo de Tabela, não há correspondência de objeto um-para-um em uma tabela no AMO; no AMO, uma tabela é representada por um Dimension e um MeasureGroup. Entretanto, para um grupo de medidas existir, é necessário definir um Cube para hospedar o grupo de medidas; além disso, para uma dimensão, um grupo de medidas e um cubo existirem, é preciso definir um objeto Exibição da Fonte de Dados para manter as definições de associação para a fonte de dados. Resumindo, para que todas as tabelas existam, são necessários uma Exibição da Fonte de Dados comum e um Cubo; a exibição da fonte de dados fornece as associações (ou mapeamentos) aos elementos de dados na dimensão e o grupo de medidas que formam uma tabela lógica; o cubo é necessário para hospedar o lado do grupo de medidas da representação de tabela.
De uma perspectiva procedural, uma Exibição da Fonte de Dados precisa ser criada antes que qualquer outro objeto seja definido. O objeto de exibição da fonte de dados contém o mapeamento para todos os objetos pertinentes, para o modelo de tabela, na fonte de dados; o mapeamento do modelo relacional é inserido na exibição da fonte de dados como um objeto do DataSet .Net e armazenado na propriedade Schema da DSV.
O trecho de código a seguir presume que você tenha uma cadeia de conexão de cliente SQL, um dicionário de instruções Select que mapeie para todas as tabelas no modelo relacional que você pretende representar em seu modelo de tabela e uma variável newDataSourceViewName com o nome da exibição da fonte de dados (geralmente o nome de seu banco de dados relacional).
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();
Quando a Exibição da Fonte de Dados tiver sido criada e atualizada, o objeto de cubo precisará ser criado, mas não atualizado no servidor até que a primeira tabela seja criada. Um objeto de cubo não pode ser criado vazio. O trecho de código a seguir mostra como criar um cubo; o trecho presume que você tenha uma cadeia de caracteres newCubeName não vazia com o nome do cubo já validado para duplicatas também.
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()));
Quando o cubo é definido localmente, as tabelas podem ser criadas e atualizadas. O procedimento a seguir destaca as etapas necessárias para criar uma tabela:
Criar a dimensão que representa a tabela e não atualizar o servidor ainda.
Criar o atributo RowNumber e defini-lo como o atributo de chave da dimensão
Criar atributos de dimensão e marcá-los com uma relação de um para muitos para RowNumber
Adicionar dimensão para dimensões de cubo
Criar o grupo de medidas que também representa a tabela
Adicionar dimensão ao grupo de medidas
Criar o objeto de medidas padrão AMO para o grupo de medidas. Observe que esta é a única hora que um objeto de medidas AMO é usado; as medidas calculadas, em modelos de tabela, são definidas no objeto MdxScripts ["MdxScript"] do AMO.
Criar partição padrão
Atualizar banco de dados
O trecho de código a seguir mostra como criar uma tabela:
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;
}
Cuidado |
---|
O trecho de código acima não tem nenhum procedimento de verificação de erros ou limpeza em caso de falha. |
Exemplo de AMO2Tabular
Para compreender como usar o AMO para criar e manipular representações de banco de dados, consulte o código-fonte do exemplo AMO para Tabela; verifique especificamente o seguinte arquivo de origem: CreateTable.cs. O exemplo está disponível em Codeplex. Uma nota importante sobre o código: o código é fornecido apenas como um suporte aos conceitos lógicos explicados aqui; ele não deve ser usado em um ambiente de produção, nem para fins que não sejam pedagógicos.