Crear tablas, particiones y columnas en un modelo tabular
Se aplica a: SQL Server 2016 y versiones posteriores Analysis Services Azure Analysis Services Fabric/Power BI Premium
En un modelo tabular, una tabla consta de filas y columnas. Las filas se organizan en particiones para admitir la actualización incremental de datos. Una solución tabular puede admitir varios tipos de tablas, dependiendo de dónde proceden los datos:
Tablas normales, donde los datos se originan en un origen de datos relacional, a través del proveedor de datos.
Tablas insertadas, donde los datos se "insertan" en la tabla mediante programación.
Tablas calculadas, donde los datos proceden de una expresión DAX que hace referencia a otro objeto dentro del modelo para sus datos.
En el ejemplo de código siguiente, definiremos una tabla normal.
Elementos obligatorios
Una tabla debe tener al menos una partición. Una tabla normal también debe tener al menos una columna definida.
Cada partición debe tener un origen que especifique el origen de los datos, pero el origen se puede establecer en null. Normalmente, el origen es una expresión de consulta que define un segmento de datos en el lenguaje de consulta de base de datos pertinente.
Ejemplo de código: crear una tabla, una columna, una partición
Las tablas se representan mediante la clase Table (en el espacio de nombres Microsoft.AnalysisServices.Tabular).
En el ejemplo siguiente, definiremos una tabla normal que tiene una partición vinculada a un origen de datos relacional y algunas columnas normales. También enviaremos los cambios al servidor y desencadenaremos una actualización de datos que lleve los datos al modelo. Esto representa el escenario más típico cuando se quieren cargar datos de una base de datos relacional de SQL Server en una solución tabular.
using System;
using Microsoft.AnalysisServices;
using Microsoft.AnalysisServices.Tabular;
namespace TOMSamples
{
class Program
{
static void Main(string[] args)
{
//
// Connect to the local default instance of Analysis Services
//
string ConnectionString = "DataSource=localhost";
//
// The using syntax ensures the correct use of the
// Microsoft.AnalysisServices.Tabular.Server object.
//
using (Server server = new Server())
{
server.Connect(ConnectionString);
//
// Generate a new database name and use GetNewName
// to ensure the database name is unique.
//
string newDatabaseName =
server.Databases.GetNewName("Database with a Table Definition");
//
// Instantiate a new
// Microsoft.AnalysisServices.Tabular.Database object.
//
var dbWithTable = new Database()
{
Name = newDatabaseName,
ID = newDatabaseName,
CompatibilityLevel = 1200,
StorageEngineUsed = StorageEngineUsed.TabularMetadata,
};
//
// Add a Microsoft.AnalysisServices.Tabular.Model object to the
// database, which acts as a root for all other Tabular metadata objects.
//
dbWithTable.Model = new Model()
{
Name = "Tabular Data Model",
Description = "A Tabular data model at the 1200 compatibility level."
};
//
// Add a Microsoft.AnalysisServices.Tabular.ProviderDataSource object
// to the data Model object created in the previous step. The connection
// string of the data source object in this example
// points to an instance of the AdventureWorks2014 SQL Server database.
//
string dataSourceName = "SQL Server Data Source Example";
dbWithTable.Model.DataSources.Add(new ProviderDataSource()
{
Name = dataSourceName,
Description = "A data source definition that uses explicit Windows credentials for authentication against SQL Server.",
ConnectionString = "Provider=SQLNCLI11;Data Source=localhost;Initial Catalog=AdventureWorks2014;Integrated Security=SSPI;Persist Security Info=false",
ImpersonationMode = Microsoft.AnalysisServices.Tabular.ImpersonationMode.ImpersonateAccount,
Account = @".\Administrator",
Password = "P@ssw0rd",
});
//
// Add a table called Individual Customers to the data model
// with a partition that points to a [Sales].[vIndividualCustomer] view
// in the underlying data source.
//
dbWithTable.Model.Tables.Add(new Table()
{
Name = dbWithTable.Model.Tables.GetNewName("Individual Customers"),
Description = "Individual customers (names and email addresses) that purchase Adventure Works Cycles products online.",
Partitions = {
//
// Create a single partition with a QueryPartitionSource for a query
// that imports all customer rows from the underlying data source.
//
new Partition() {
Name = "All Customers",
Source = new QueryPartitionSource() {
DataSource = dbWithTable.Model.DataSources[dataSourceName],
Query = @"SELECT [FirstName]
,[MiddleName]
,[LastName]
,[PhoneNumber]
,[EmailAddress]
,[City]
FROM [Sales].[vIndividualCustomer]",
}
}
},
Columns =
{
//
// DataColumn objects refer to regular table columns.
// Each DataColumn object corresponds to a column in the underlying data source query.
//
new DataColumn() {
Name = "FirstName",
DataType = DataType.String,
SourceColumn = "FirstName",
},
new DataColumn() {
Name = "MiddleName",
DataType = DataType.String,
SourceColumn = "MiddleName",
},
new DataColumn() {
Name = "LastName",
DataType = DataType.String,
SourceColumn = "LastName",
},
new DataColumn() {
Name = "PhoneNumber",
DataType = DataType.String,
SourceColumn = "PhoneNumber",
},
new DataColumn() {
Name = "EmailAddress",
DataType = DataType.String,
SourceColumn = "EmailAddress",
},
new DataColumn() {
Name = "City",
DataType = DataType.String,
SourceColumn = "City",
},
}
});
//
// Add the new database object to the server's
// Databases connection and submit the changes
// with full expansion to the server.
//
server.Databases.Add(dbWithTable);
//
// Request a full refresh to import the data from the data source and
// and perform any necessary recalculations.
// The refresh operation will be performed with the next
// invocation of Model.SaveChanges() or Database.Update(UpdateOptions.ExpandFull).
dbWithTable.Model.RequestRefresh(Microsoft.AnalysisServices.Tabular.RefreshType.Full);
dbWithTable.Update(UpdateOptions.ExpandFull);
Console.Write("Database ");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write(dbWithTable.Name);
Console.ResetColor();
Console.WriteLine(" created successfully.");
Console.WriteLine("The data model includes the following table definitions:");
Console.ForegroundColor = ConsoleColor.Yellow;
foreach (Table tbl in dbWithTable.Model.Tables)
{
Console.WriteLine("\tTable name:\t\t{0}", tbl.Name);
Console.WriteLine("\ttbl description:\t{0}", tbl.Description);
}
Console.ResetColor();
Console.WriteLine();
}
Console.WriteLine("Press Enter to close this console window.");
Console.ReadLine();
}
}
}
Particiones en una tabla
Las particiones se representan mediante una clase Partition (en el espacio de nombres Microsoft.AnalysisServices.Tabular). La clase Partition expone una propiedad Source del tipo PartitionSource , que proporciona una abstracción sobre los diferentes enfoques para ingerir datos en la partición. Una instancia de partición puede tener una propiedad Source como null, lo que indica que los datos se insertarán en la partición mediante el envío de fragmentos de datos al servidor como parte de la API de inserción de datos expuesta por Analysis Services. En SQL Server 2016, la clase PartitionSource tiene dos clases derivadas que representan formas de enlazar datos a una partición: QueryPartitionSource y CalculatedPartitionSource.
Columnas de una tabla
Las columnas se representan mediante varias clases derivadas de la clase Column base (en el espacio de nombres Microsoft.AnalysisServices.Tabular):
- DataColumn (para columnas normales en tablas normales)
- CalculatedColumn (para columnas respaldadas por la expresión DAX)
- CalculatedTableColumn (para columnas normales en tablas calculadas)
- RowNumberColumn (tipo especial de columna creada por SSAS para cada tabla).
Números de fila en una tabla
Cada objeto Table de un servidor tiene un objeto RowNumberColumn que se usa con fines de indexación. No se puede crear ni agregar explícitamente. La columna se crea automáticamente al guardar o actualizar el objeto:
Db. SaveChanges
Db. Update(ExpandFull)
Al llamar a cualquiera de los métodos, el servidor creará automáticamente la columna de números de fila, que será visible como RowNumberColumn la colección Columns de la tabla.
Tablas calculadas
Las tablas calculadas proceden de una expresión DAX que vuelve a usar datos de estructuras de datos existentes en el modelo o de enlaces fuera de línea. Para crear una tabla calculada mediante programación, haga lo siguiente:
Cree una tabla genérica.
Agregue una partición a ella con Source de tipo CalculatedPartitionSource, donde el origen es una expresión DAX. El origen de la partición es lo que diferencia una tabla normal de una tabla calculada.
Al guardar los cambios en el servidor, el servidor devolverá la lista inferida de CalculatedTableColumns (las tablas calculadas se componen de columnas de tabla calculadas), visibles a través de la colección Columns de la tabla.
Paso siguiente
Revise las clases usadas para controlar excepciones en TOM: Control de errores en TOM