Estensione delle funzionalità di database di Visual Studio
È possibile estendere Visual Studio Premiumo Visual Studio Ultimate creando estensioni di funzionalità. Queste estensioni di funzionalità consentono di estendere le funzionalità di Visual Studio Premium or Visual Studio Ultimate, ad esempio refactoring, generazione di dati, unit test e analisi codice del database. Per creare estensioni di funzionalità, viene utilizzato un framework esistente per la funzionalità di base, in modo da ridurre sensibilmente la quantità di codice che è necessario scrivere.
Le estensioni di funzionalità dispongono di punti di estensibilità ben definiti. Non è necessario avere installato Visual Studio SDK per creare estensioni di funzionalità per Visual Studio Premium o Visual Studio Ultimate.
Attività comuni di alto livello
Attività di alto livello |
Contenuto di supporto |
---|---|
Informazioni sui concetti di estensibilità del database: prima di estendere tali funzionalità, è necessario conoscere le modalità di funzionamento dell'estensibilità in Visual Studio Premium o Visual Studio Ultimate. Un provider dello schema di database implementa tutti i servizi specifici di un marchio e una versione particolari di un database (ad esempio SQL Server 2008). Sono inclusi il parser che legge e scrive gli script per tale database, il modello a oggetti del dominio di script (modello DOM di script) che rappresenta gli script e il modello di schema che modella gli oggetti, le relazioni e le proprietà degli oggetti di database. Quando in Visual Studio Premium o Visual Studio Ultimate si interagisce con una funzionalità o un'estensione di funzionalità, tali funzionalità ed estensioni di funzionalità agiscono in base a una combinazione dei servizi DSP, del DOM di Script e del modello di schema. |
|
Aggiungere il supporto per nuovi tipi di refactoring del database: è possibile creare estensioni di funzionalità affinché il refactoring del database abiliti i nuovi tipi di refactoring del database. Ogni nuovo tipo di refactoring richiede inoltre uno o più i nuovi collaboratori di refactoring. |
|
Aggiungere il supporto per nuove destinazioni di refactoring del database: è possibile consentire a un tipo esistente di refactoring del database di aggiornare un nuovo tipo di elemento, ad esempio un file di testo, o di restituire l'output da un'applicazione di terze parti che contiene informazioni sul database. Se si crea un nuovo tipo di refactoring, è necessario implementare uno o più collaboratori di refactoring per consentire il funzionamento di tale tipo con gli elementi contenuti nel progetto di database. |
|
Definire nuove regole di analisi codice del database: è possibile definire nuove regole di analisi codice del database per la ricerca di problemi che non vengono rilevati dalle regole incluse in Visual Studio Premium o Visual Studio Ultimate. |
|
Creare generatori di dati personalizzati: è possibile utilizzare i generatori di dati personalizzati per generare dati di test realistici che non rivelino informazioni riservate. È possibile creare generatori di dati personalizzati per completare i generatori di dati contenuti in Visual Studio Premium o Visual Studio Ultimate. |
|
Aggiungere condizioni di unit test del database personalizzate: mediante la definizione di una condizione di test personalizzata è possibile verificare il comportamento di un oggetto di database in modi non supportati dalle condizioni di unit test incorporate. |
|
Personalizzare il comportamento del progetto di database: definendo una funzionalità del progetto di database personalizzata, è possibile modificare il comportamento del progetto in modi che i progetti di database incorporati non supportano. |
Modellazione di un database
Per modellare un database, in Visual Studio vengono modellati sia gli script che costituiscono il linguaggio DDL (Data Definition Language) del database e il database che verrebbe generato dall'esecuzione di tali script. Il modello degli script DDL viene fornito dal modello DOM di script. Il modello del database risultante viene fornito dal modello dello schema.
Flusso di dati tra componenti di estensibilità
Il diagramma seguente mostra il flusso dei dati attraverso questi componenti.
Flusso di dati tra componenti di estensibilità
Le definizioni degli oggetti di database vengono salvate in modo permanente nel progetto di database sotto forma di script DDL. Quando si apre un progetto di database, tali script vengono letti e vengono popolati due modelli: il modello DOM di script e il modello dello schema. Funzionalità di Visual Studio Premium interagiscono con entrambi i modelli e quando si salvano modifiche negli oggetti di database, tali modifiche vengono salvate di nuovo in modo permanente negli script DDL.
Componenti di estensibilità in Database Edition
Nel diagramma seguente vengono mostrati i componenti che interagiscono per consentire l'estensione delle funzionalità di Database Edition.
Comunicazione tra componenti di estensibilità
Quando si apre o si crea un progetto di database qualsiasi, il componente Gestione estensioni carica tutti i provider dello schema di database registrati. Quando si utilizzano funzionalità particolari per un provider dello schema di database (DSP), il componente Gestione estensioni carica le funzionalità e le relative estensioni che supportano il DSP. Quando, ad esempio, si utilizzano le funzionalità di refactoring di ridenominazione per rinominare oggetti in un database di SQL Server 2008, la funzionalità di refactoring viene caricata insieme ai tipi e ai collaboratori di refactoring per SQL Server 2008.
Gestione estensioni
Quando si esegue Visual Studio Premium o Visual Studio Ultimate, tutti i progetti di database, i provider dello schema, le funzionalità e le estensioni di funzionalità interagiscono con il singleton ExtensionManager. Gestione estensioni carica una sola istanza derivata da DatabaseSchemaProvider per ogni progetto di database. Ad esempio, quando Visual Studio Premium o Visual Studio Ultimate apre un progetto Microsoft SQL Server 2005, Gestione estensioni carica un'istanza di Sql90DatabaseSchemaProvider (derivata da DatabaseSchemaProvider).
Gestione estensioni carica estensioni in base al tipo di interfaccia implementata da tali estensioni. Ad esempio, quando si utilizza la funzionalità di unit test del database, Gestione estensioni restituisce un elenco di estensioni registrate che ereditano la classe base TestCondition e le cui estensioni sono compatibili con il provider dello schema di database per il progetto di database.
Compatibilità dell'estensione di funzionalità
Una funzionalità, ad esempio refactoring o analisi codice statica, è costituita da componenti specifici di un provider dello schema di database (DSP) e componenti che supportano tutti i DSP (componenti indipendenti dal DSP). Quando si definisce un'estensione di funzionalità, si dichiara la compatibilità di tale estensione con un DSP specifico o un DSP di base, in modo che l'estensione venga caricata solo per i tipi di progetto appropriati. Ad esempio, è possibile dichiarare che l'estensione è compatibile sia con Sql90DatabaseSchemaProvider (per limitarlo ai progetti SQL Server 2005) o con SqlDatabaseSchemaProvider (la classe base per i DSP di SQL Server 2005 e SQL Server 2008). È inoltre possibile dichiarare un'estensione in modo che sia compatibile con più DSP specifici. È possibile utilizzare questo approccio qualora si dubiti che le versioni successive possano interrompere la funzionalità. Per dichiarare una funzionalità in modo che sia compatibile con tutti i DSP, dichiararne la compatibilità con la classe base DatabaseSchemaProvider.
Esempi
Definire un'estensione compatibile con un DSP:
// SqlSchemaObjectDesigners is defined as compatible with all Sql
// database services providers.
[DatabaseSchemaProviderCompatibility (typeof(Sql90DatabaseSchemaProvider))]
internal class SqlSchemaObjectDesigners : ISchemaObjectDesigners
{
}
Definire un'estensione compatibile con più DSP:
// Extension InconclusiveCondition is defined as compatible with all
// SQL Server database services providers and Oracle database
// services providers.
[DatabaseSchemaProviderCompatibility (typeof(SqlDatabaseSchemaProvider))]
[DatabaseSchemaProviderCompatibility (typeof(OracleDatabaseSchemaProvider))]
public sealed class InconclusiveCondition : TestCondition
{
}
Definire un'estensione compatibile con tutti i DSP:
// Extension ReportingService is defined as compatible with all
// database services providers.
[DatabaseSchemaProviderCompatibility (typeof(DatabaseSchemaProvider))]
internal class ReportingService : IReportingService
{
}
Definire un'estensione compatibile con nessun DSP:
// Extension ExecutionTimeCondition is defined as compatible with no
// database services providers. That means if a feature
// has an ExtensionManager constructed with null, it will load
// those extensions defined as binding to
// DspCompatibilityCategory.None
[DatabaseSchemaProviderCompatibility (DspCompatibilityCategory.None)]
public sealed class ExecutionTimeCondition : TestCondition
{
}
Tipi di estensioni di funzionalità
È possibile creare estensioni di funzionalità affinché migliorino alcune funzionalità di Visual Studio Premium o Visual Studio Ultimate. Nella tabella seguente vengono descritti i tipi di estensioni che è possibile creare.
Funzionalità |
Tipo di estensione |
Descrizione |
---|---|---|
Unit test del database |
Condizioni di unit test |
È possibile aggiungere asserzioni personalizzate per determinare l'esito positivo o negativo dei test. La maggior parte delle API di unit test è pubblica ma non rappresenta un punto di estensibilità. Tali API vengono utilizzate per creare unit test del database scritti in codice gestito, ad esempio Visual C# o Visual Basic. Per ulteriori informazioni, vedere Definire condizioni personalizzate per gli unit test del database. |
Generazione dati |
Generatori di dati |
È possibile utilizzare l'API di estensibilità per creare generatori di dati personalizzati se i generatori di dati vengono forniti con Visual Studio Premium o Visual Studio Ultimate. Per ulteriori informazioni, vedere Generare dati di test specializzati con un generatore di dati personalizzato. |
Analisi codice del database |
Regole dell'analisi del codice |
È possibile definire regole di analisi codice per verificare problemi specifici nel codice del database. Per ulteriori informazioni, vedere Creare e registrare regole aggiuntive per l'analisi del codice del database. |
Refactoring del database |
Destinazioni di refactoring |
È possibile estendere i tipi di refactoring esistenti in modo da poterli utilizzare in nuove destinazioni, ad esempio nuovi tipi di file. Per ulteriori informazioni, vedere Procedura dettagliata: estensione del refactoring di ridenominazione del database affinché operi su file di testo. |
Refactoring del database |
Tipi di refactoring |
È possibile creare i nuovi tipi di refactoring, ad esempio sostituire condizionali annidati con clausole di protezione. Per ulteriori informazioni, vedere Creare tipi o destinazioni di refactoring del database personalizzati. |
Componenti di base dei provider dello schema di database
Un provider dello schema di database (DSP) è costituito da tre gruppi di componenti:
DOM di Script: un modello a oggetti e servizi di supporto che modellano un script SQL arbitrario che include sia istruzioni DDL che DML.
Modello di schema: un modello a oggetti e servizi di supporto che modellano gli oggetti in un'istanza del database, ad esempio tabelle, visualizzazioni e stored procedure.
Servizi di interazione dell'utente: un insieme di servizi che consentono ai componenti di base di accedere alle risorse dell'interfaccia utente, ad esempio le stringhe che rappresentano i nomi di oggetti, le icone che rappresentano i tipi di oggetti e le categorie, nonché le gerarchie in cui visualizzare tali oggetti.
Le funzioni primarie di un DSP consistono nell'abilitare l'elaborazione di script DDL in rappresentazioni sia del DOM di script che del modello di schema e nell'abilitare la funzione inversa di riprodurre script dalle due rappresentazioni del modello.
DOM di script
Un DOM di Script fornisce l'implementazione che analizza uno script DDL in un modello a oggetti che rappresenta lo script. Il DOM di script fornisce inoltre l'implementazione per riprodurre lo script originale dal modello.
Nel diagramma seguente è illustrato mostra il flusso di dati attraverso il DOM di script.
Flusso di dati attraverso il DOM di script
Il parser del DOM di script converte lo script, archiviato in un file di testo non strutturato, in un oggetto che eredita l'interfaccia IScriptFragment. Il generatore di script nel DOM di script accetta un oggetto che eredita l'interfaccia IScriptFragment e produce lo script originale. Nei provider dello schema di database per SQL Server, inclusi in Visual Studio Premium o Visual Studio Ultimate, IScriptFragment estrae una struttura ad albero sintattica astratta e un flusso del token.
I token forniscono una rappresentazione non strutturata di uno script. Ogni token nell'insieme dispone dei seguenti elementi:
Il tipo di token (ad esempio parola chiave o valore letterale stringa)
La stringa del token
Il file di origine in cui si è verificato il token
L'offset all'interno del file in cui si è verificato il token
Le strutture ad albero sintattiche astratte forniscono una rappresentazione strutturata dello script. Ogni nodo nella struttura ad albero sintattica astratta rappresenta un batch di istruzioni, un'istruzione o un componente di un'istruzione (ad esempio un'espressione). Le strutture ad albero sintattiche astratte vengono utilizzate per esaminare script dopo che sono stati analizzati. Vengono inoltre utilizzate per compilare script a livello di codice.
Modello di schema
La rappresentazione del modello di schema è un modello a oggetti basato sull'interfaccia che modella un'istanza del database attiva. Le interfacce vengono disposte in una gerarchia di derivazione che include un solo livello astratto condiviso da tutti i DSP, oltre a un numero qualsiasi di livelli astratti destinati ai dettagli del modello più specifici. Ad esempio, l'interfaccia ISql90Table eredita ISqlTable, che a sua volta eredita l'interfaccia del livello astratto IDatabaseTable. Il modello di schema accetta gli oggetti IScriptFragment e li converte in elementi del modello di schema, eseguendo inoltre la conversione inversa, da elementi del modello di schema in oggetti IScriptFragment. Il modello di schema è costituito da alcune implementazioni del compositore del modello. Ogni implementazione crea un modello da un'altra risorsa presente nel sistema. Ad esempio, ScriptModelComposer crea un modello dai file di script gestiti nel progetto di database.
L'infrastruttura del modello di schema (ModelStore e le classi di supporto) implementa riferimenti integrati al DOM di Script direttamente dagli elementi del modello. Ciò abilita la modellazione di oggetti, ad esempio stored procedure, che contengono script arbitrari.
Un modello di schema è costituito da un insieme di elementi e annotazioni. Gli elementi descrivono l'elemento in fase di modellazione (ad esempio tabelle, visualizzazioni, stored procedure, trigger, colonne e così via). Le annotazioni vengono utilizzate per associare dati arbitrari al modello. Le annotazioni vengono utilizzate dai componenti di base del progetto di database e possono essere utilizzati anche da funzionalità del progetto e da estensioni di funzionalità. Sia gli elementi che le annotazioni possono essere denominati o anonimi.
Elementi del modello
Gli elementi sono costituiti da proprietà e relazioni. Le proprietà rappresentano dati di base, ad esempio Integer, valori booleani e stringhe, e vengono utilizzate per acquisire i dettagli del modello. Le relazioni rappresentano connessioni denominate e tipizzate tra elementi. Ad esempio, un elemento ISqlTable gestisce una relazione di tipo ISqlColumn denominata "Colonne" che associa la tabella alle colonne.
Esistono tre tipi di relazioni di base:
Peer: rappresenta una dipendenza da un elemento a un altro elemento in modo arbitrario. In SQL Server la relazione tra una visualizzazione e una tabella viene modellata più correttamente come una relazione peer.
Composta: rappresenta un elemento costituito da altri elementi. In SQL Server la relazione tra una tabella e le relative colonne viene modellata più correttamente come una relazione composta. Un principio importante di una relazione composta è costituito dal fatto che i due elementi vengono creati contemporaneamente, come una sola azione. Gli elementi non dispongono di un ordine di dipendenza per la creazione o la rimozione. La direzione della dipendenza da padre a figlio viene tuttavia gestita dal modello per abilitare dipendenze associative. Ad esempio, se una colonna dispone di una dipendenza da un tipo particolare, la dipendenza della tabella padre dalla relativa colonna di composizione significa che la tabella dipende anche dal tipo.
Gerarchica: rappresenta una gerarchia. Le relazioni gerarchiche differiscono dalle relazioni composte perché la direzione della dipendenza è da figlio a padre (anziché viceversa). Un esempio in SQL Server è la relazione tra un schema e un oggetto di proprietà, ad esempio una tabella o una visualizzazione. Una tabella partecipa a una relazione gerarchica con il relativo schema.
Nel diagramma seguente vengono illustrati i tre tipi diversi di relazioni che possono essere rappresentate nel modello di schema.
Relazioni di oggetti nel modello schema
Ogni relazione in un modello dichiara se è una relazione multipla o singola. In tutti i casi, un elemento può gestire una relazione vuota. I modelli possono essere modelli incompleti dell'elemento reale.
Gli elementi sono basati sull'interfaccia per supportare le funzionalità seguenti in un'implementazione dell'archivio:
Tipizzazione forte dell'elemento (identità)
Ereditarietà multipla
Per supportare parti del sistema sia indipendenti che specifici del provider dello schema di database (DSP)
Per supportare la condivisione di "qualità" tra tipi di elementi diversamente non correlati
Flessibilità ed estensibilità della versione
Tutte le classi degli elementi del modello implementano l'interfaccia pubblica IModelElement. L'accesso a proprietà, relazioni e annotazioni può essere eseguito da questa classe tramite l'API dei metadati ModelStore. Le interfacce, ad esempio IDatabaseTable, vengono utilizzate per fornire l'accesso (associate in fase di compilazione) a proprietà e relazioni in modo più semplice e più gestibile.
Annotazione del modello
Come gli elementi, le annotazioni sono costituite da proprietà. A differenza degli elementi, le annotazioni non partecipano alle relazioni. Al contrario, le annotazioni sono associate agli elementi o allo stesso archivio modelli. Le annotazioni sono fortemente tipizzate e una sola istanza di un'annotazione può essere associata a più elementi oltre all'archivio modelli. Le annotazioni associate al modello rappresentano un'istanza di annotazione "globale" per il modello.