Creare tabelle, partizioni e colonne in un modello tabulare

Si applica a: SQL Server 2016 e versioni successive di Analysis Services Azure Analysis Services Fabric/Power BI Premium

In un modello tabulare una tabella è costituita da righe e colonne. Le righe sono organizzate in partizioni per supportare l'aggiornamento incrementale dei dati. Una soluzione tabulare può supportare diversi tipi di tabelle, a seconda della provenienza dei dati:

  • Tabelle regolari, in cui i dati provengono da un'origine dati relazionale, tramite il provider di dati.

  • Tabelle push, in cui i dati vengono "push" nella tabella a livello di codice.

  • Tabelle calcolate, dove i dati provengono da un'espressione DAX che fa riferimento a un altro oggetto all'interno del modello per i dati.

Nell'esempio di codice seguente verrà definita una tabella regolare.

Elementi obbligatori

Una tabella deve avere almeno una partizione. Una tabella regolare deve avere almeno una colonna definita.

Ogni partizione deve avere un'origine che specifica l'origine dei dati, ma l'origine può essere impostata su Null. In genere, l'origine è un'espressione di query che definisce una sezione di dati nel linguaggio di query di database pertinente.

Esempio di codice: creare una tabella, una colonna, una partizione

Le tabelle sono rappresentate dalla classe Table (nello spazio dei nomi Microsoft.AnalysisServices.Tabulare).

Nell'esempio seguente verrà definita una tabella regolare con una partizione collegata a un'origine dati relazionale e a alcune colonne regolari. Verranno inoltre inviate le modifiche al server e verrà attivato un aggiornamento dei dati che porta i dati nel modello. Questo rappresenta lo scenario più tipico quando si desidera caricare i dati da un database relazionale SQL Server in una soluzione tabulare.

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(); 
        } 
    } 
} 

Partizioni in una tabella

Le partizioni sono rappresentate da una classe Partition (nello spazio dei nomi Microsoft.AnalysisServices.Tabulare). La classe Partition espone una proprietà Source del tipo PartitionSource , che fornisce un'astrazione rispetto ai diversi approcci per inserire i dati nella partizione. Un'istanza di partizione può avere una proprietà Source come Null, che indica che i dati verranno inseriti nella partizione inviando blocchi di dati al server come parte dell'API dati push esposta da Analysis Services. In SQL Server 2016 la classe PartitionSource include due classi derivate che rappresentano i modi per associare i dati a una partizione: QueryPartitionSource e CalculatedPartitionSource.

Colonne in una tabella

Le colonne sono rappresentate da diverse classi derivate dalla classe Column di base (nello spazio dei nomi Microsoft.AnalysisServices.Tabulare):

  • DataColumn (per le colonne regolari nelle tabelle regolari)
  • CalculatedColumn (per le colonne supportate dall'espressione DAX)
  • CalculatedTableColumn (per le colonne regolari nelle tabelle calcolate)
  • RowNumberColumn (tipo speciale di colonna creato da SSAS per ogni tabella).

Numeri di riga in una tabella

Ogni oggetto Table in un server ha un rowNumberColumn usato per scopi di indicizzazione. Non è possibile crearlo o aggiungerlo in modo esplicito. La colonna viene creata automaticamente quando si salva o si aggiorna l'oggetto:

  • Db. Savechanges

  • Db. Update(ExpandFull)

Quando si chiama un metodo, il server creerà automaticamente la colonna del numero di riga, che sarà visibile come RowNumberColumn l'insieme Columns della tabella.

Tabelle calcolate

Le tabelle calcolate vengono generate da un'espressione DAX che consente di ripetere i dati dalle strutture di dati esistenti nel modello o da associazioni fuori riga. Per creare una tabella calcolata a livello di codice, eseguire le operazioni seguenti:

  • Creare una tabella generica.

  • Aggiungere una partizione a essa con Origine di tipo CalculatedPartitionSource, dove l'origine è un'espressione DAX. L'origine della partizione è ciò che differenzia una tabella regolare da una tabella calcolata.

Quando si salvano le modifiche al server, il server restituirà l'elenco dedotto di CalculatedTableColumns (tabelle calcolate sono costituite da colonne di tabella calcolate), visibili tramite l'insieme Columns della tabella.

Passaggio successivo

Esaminare le classi usate per gestire le eccezioni in TOM: Gestione degli errori in TOM