Condividi tramite


Procedura dettagliata: estendere la distribuzione del progetto di database per analizzare il piano di distribuzione

È possibile creare collaboratori alla distribuzione per eseguire azioni personalizzate quando si distribuisce un progetto di database. È possibile creare un DeploymentPlanModifier o un DeploymentPlanExecutor. Utilizzare un DeploymentPlanModifier per modificare il piano prima che venga eseguito e un DeploymentPlanExecutor per eseguire operazioni mentre il piano viene eseguito. In questa procedura dettagliata, si creerà un DeploymentPlanExecutor denominato DeploymentUpdateReportContributor che crea un rapporto sulle azioni eseguite quando si distribuisce un progetto di database. Poiché questo collaboratore alla compilazione accetta un parametro per controllare se viene generato il rapporto, è necessario eseguire un passaggio obbligatorio aggiuntivo.

In questa procedura dettagliata si completeranno le seguenti attività principali:

  • Creare il tipo DeploymentPlanExecutor di collaboratore alla distribuzione

  • Installare il collaboratore alla distribuzione

  • Testare il collaboratore alla distribuzione

Prerequisiti

Per completare la procedura dettagliata, è necessario disporre dei componenti seguenti:

  • Visual Studio 2010 Premium o Visual Studio 2010 Ultimate installato nel computer.

  • Un progetto di database contenente oggetti di database.

  • Un'istanza di SQL Server alla quale è possibile distribuire un progetto di database

Nota

Questa procedura dettagliata è destinata a utenti che hanno già familiarità con le funzionalità di database di Visual Studio. È inoltre necessario conoscere i concetti di base di Visual Studio, ad esempio come creare una libreria di classi e come utilizzare l'editor di codice per aggiungere codice a una classe.

Creare un collaboratore alla distribuzione

Per creare un collaboratore alla distribuzione, è necessario effettuare le attività seguenti:

  • Creare un progetto Libreria di classi e aggiungere riferimenti obbligatori

  • Definire una classe denominata DeploymentUpdateReportContributor che eredita da DeploymentPlanExecutor

  • Eseguire l'override dei metodi OnPopulateArguments e OnExecute.

  • Aggiungere una classe di supporto privata

  • Compilare l'assembly risultante

Per creare un progetto Libreria di classi

  1. Creare un progetto Libreria di classi di Visual Basic or Visual C# denominato MyDeploymentContributor.

  2. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Riferimenti e scegliere Aggiungi riferimento.

  3. Fare clic sulla scheda .NET.

  4. Evidenziare le voci Microsoft.Data.Schema e Microsoft.Data.Schema.Sql e fare clic su OK.

    Iniziare quindi ad aggiungere codice alla classe.

Per definire la classe DeploymentUpdateReportContributor

  1. Nell'editor di codice aggiornare il file class1.cs affinché corrisponda alle seguenti istruzioni using o Imports:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Data.Schema.Build;
    using Microsoft.Data.Schema.Extensibility;
    using Microsoft.Data.Schema.Sql;
    using System.IO;
    using Microsoft.Data.Schema.SchemaModel;
    using System.Xml;
    using Microsoft.Data.Schema;
    using Microsoft.Data.Schema.Sql.Build;
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports Microsoft.Data.Schema.Build
    Imports Microsoft.Data.Schema.Extensibility
    Imports Microsoft.Data.Schema.Sql
    Imports System.IO
    Imports Microsoft.Data.Schema.SchemaModel
    Imports System.Xml
    Imports Microsoft.Data.Schema
    Imports Microsoft.Data.Schema.Sql.Build
    
  2. Aggiornare la definizione della classe come segue:

        [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
        class DeploymentUpdateReportContributor : DeploymentPlanExecutor
        {
        }
    
    ''' <summary>
    ''' The DeploymentUpdateReportContributor class demonstrates
    ''' how you can create a class that inherits DeploymentPlanExecutor
    ''' to perform actions when you execute the deployment plan
    ''' for a database project.
    ''' </summary>
    <DatabaseSchemaProviderCompatibility(GetType(SqlDatabaseSchemaProvider))>
    Public Class DeploymentUpdateReportContributor
        Inherits DeploymentPlanExecutor
    End Class
    

    A questo punto è stato definito il collaboratore alla compilazione e utilizzato l'attributo per indicare che questo collaboratore è compatibile con qualsiasi provider dello schema di database che eredita da SqlDatabaseSchemaProvider.

  3. Si aggiungerà quindi il seguente membro che verrà utilizzato per consentire a questo provider di accettare un parametro da riga di comando:

            private const string GenerateUpdateReport = "GenerateUpdateReport";
    
        Dim GenerateUpdateReport As String = "GenerateUpdateReport"
    

    Questo membro consente all'utente di specificare se il rapporto deve essere generato tramite l'opzione GenerateUpdateReport.

    Si eseguirà quindi l'override del metodo OnPopulateArguments per compilare l'elenco di argomenti da passare al collaboratore alla distribuzione.

Per eseguire l'override di OnPopulateArguments

  • Aggiungere alla classe DeploymentUpdateReportContributor il seguente metodo di override:

        /// <summary>
        /// Override the OnPopulateArgument method to build a list of arguments from the input
        /// configuration information.
        /// </summary>
            protected override IList<ContributorArgumentConfiguration> OnPopulateArguments()
            {
                List<ContributorArgumentConfiguration> args = new List<ContributorArgumentConfiguration>();
    
                // Generate reports when in debug configuration
                args.Add(new ContributorArgumentConfiguration( GenerateUpdateReport, "true", "'$(Configuration)' == 'Debug'"));
                return args;
            }
    
        ''' <summary>
        ''' Override the OnPopulateArgument method to build a list of arguments from the input
        ''' configuration information.
        ''' </summary>
        Protected Overloads Overrides Function OnPopulateArguments() As IList(Of ContributorArgumentConfiguration)
            Dim args As New List(Of ContributorArgumentConfiguration)()
    
            ' Generate reports when in debug configuration 
            args.Add(New ContributorArgumentConfiguration(GenerateUpdateReport, "true", "'$(Configuration)' == 'Debug'"))
            Return args
        End Function
    

    È stato compilato un oggetto ContributorArgumentConfiguration, che è stato aggiunto all'elenco di argomenti. Per impostazione predefinita, il rapporto viene generato quando si genera una build di debug.

    Eseguire quindi l'override del metodo OnExecute per aggiungere il codice che si desidera eseguire quando viene distribuito un progetto di database.

Per eseguire l'override di OnExecute

  • Aggiungere alla classe DeploymentUpdateReportContributor il seguente metodo:

        /// <summary>
        /// Override the OnExecute method to perform actions when you execute the deployment plan for
        /// a database project.
        /// </summary>
            protected override void OnExecute(DeploymentPlanContributorContext context)
            {
                // determine whether the user specified a report is to be generated
                bool generateReport = false;
                string generateReportValue;
                if (context.Arguments.TryGetValue(GenerateUpdateReport, out generateReportValue) == false)
                {
                    // couldn't find the GenerateUpdateReport argument, so do not generate
                    generateReport = false;
                }
                else
                {
                    // GenerateUpdateReport argument was specified, try to parse the value
                    if (bool.TryParse(generateReportValue, out generateReport))
                    {
                        // if we end up here, the value for the argument was not valid.
                        // default is false, so do nothing.
                    }
                }
    
                if (generateReport == false)
                {
                    // if user does not want to generate a report, we are done
                    return;
                }
    
                // We will output to the same directory where the deployment script
                // is output or to the current directory
                string reportPrefix = context.Options.TargetDatabaseName;
                string reportPath;
                if (string.IsNullOrEmpty(context.DeploymentScriptPath))
                {
                    reportPath = Environment.CurrentDirectory;
                }
                else
                {
                    reportPath = Path.GetDirectoryName(context.DeploymentScriptPath);
                }
                FileInfo summaryReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".summary.xml"));
                FileInfo detailsReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".details.xml"));
    
                // Generate the reports by using the helper class DeploymentReportWriter
                DeploymentReportWriter writer = new DeploymentReportWriter(context);
                writer.WriteReport(summaryReportFile);
                writer.IncludeScripts = true;
                writer.WriteReport(detailsReportFile);
    
                string msg = "Deployment reports ->"
                    + Environment.NewLine + summaryReportFile.FullName
                    + Environment.NewLine + detailsReportFile.FullName;
    
                DataSchemaError reportMsg = new DataSchemaError(msg, ErrorSeverity.Message);
                base.PublishMessage(reportMsg);
            }
    
        ''' <summary>
        ''' Override the OnExecute method to perform actions when you execute the deployment plan for
        ''' a database project.
        ''' </summary>
        Protected Overloads Overrides Sub OnExecute(ByVal context As DeploymentPlanContributorContext)
            ' output the names and values for any provided arguments 
            For Each arg As KeyValuePair(Of String, String) In context.Arguments
                Dim argMsg As New DataSchemaError((arg.Key & "=") + arg.Value, ErrorSeverity.Message)
                Me.PublishMessage(argMsg)
            Next
            ' determine whether the user specified a report is to be generated 
            Dim generateReport As Boolean = False
            Dim generateReportValue As String
            If context.Arguments.TryGetValue(GenerateUpdateReport, generateReportValue) = False Then
                ' couldn't find the GenerateUpdateReport argument, so do not generate 
                generateReport = False
            Else
                ' GenerateUpdateReport argument was specified, try to parse the value 
                If Boolean.TryParse(generateReportValue, generateReport) Then
                    ' if we end up here, the value for the argument was not valid. 
                    ' default is false, so do nothing. 
                End If
            End If
    
            If generateReport = False Then
                ' if user does not want to generate a report, we are done 
                Exit Sub
            End If
    
            ' We will output to the same directory where the deployment script 
            ' is output or to the current directory 
            Dim reportPrefix As String = context.Options.TargetDatabaseName
            Dim reportPath As String
            If String.IsNullOrEmpty(context.DeploymentScriptPath) Then
                reportPath = Environment.CurrentDirectory
            Else
                reportPath = Path.GetDirectoryName(context.DeploymentScriptPath)
            End If
            Dim summaryReportFile As New FileInfo(Path.Combine(reportPath, reportPrefix & ".summary.xml"))
            Dim detailsReportFile As New FileInfo(Path.Combine(reportPath, reportPrefix & ".details.xml"))
    
            ' Generate the reports by using the helper class DeploymentReportWriter 
            Dim writer As New DeploymentReportWriter(context)
            writer.WriteReport(summaryReportFile)
            writer.IncludeScripts = True
            writer.WriteReport(detailsReportFile)
    
            Dim msg As String = ("Deployment reports ->" & Environment.NewLine) + summaryReportFile.FullName + Environment.NewLine + detailsReportFile.FullName
    
            Dim reportMsg As New DataSchemaError(msg, ErrorSeverity.Message)
            MyBase.PublishMessage(reportMsg)
        End Sub
    

    Al metodo OnExecute viene passato un oggetto DeploymentPlanContributorContext che fornisce l'accesso a qualsiasi argomento specificato, al modello del database di origine e di destinazione, alle proprietà di compilazione e ai file di estensione. In questo esempio, si leggerà il modello, quindi si chiameranno funzioni di supporto per restituire informazioni sul modello. Al metodo viene passato anche un oggetto ErrorManager da utilizzare per segnalare gli eventuali errori che dovessero verificarsi.

    Tipi e metodi di interesse aggiuntivi includono: DataSchemaModel, ModelStore, ModelComparisonResult , DatabaseSchemaProvider , DeploymentPlanHandle e SchemaDeploymentOptions.

    Si definirà quindi la classe di supporto che analizza i dettagli del piano di distribuzione.

Per aggiungere la classe di supporto che genera il corpo del rapporto

  • Aggiungere innanzitutto scheletri della classe di supporto e i relativi metodi tramite il codice seguente:

            /// <summary>
            /// This class is used to generate a deployment
            /// report. 
            /// </summary>
            private class DeploymentReportWriter
            {
                /// <summary>
                /// The constructor accepts the same context info
                /// that was passed to the OnExecute method of the
                /// deployment contributor.
                /// </summary>
                public DeploymentReportWriter(DeploymentPlanContributorContext context)
                {
               }
                /// <summary>
                /// Property indicating whether script bodies
                /// should be included in the report.
                /// </summary>
                public bool IncludeScripts { get; set; }
    
                /// <summary>
                /// Drives the report generation, opening files, 
                /// writing the beginning and ending report elements,
                /// and calling helper methods to report on the
                /// plan operations.
                /// </summary>
                internal void WriteReport(FileInfo reportFile)
                {
                }
    
                /// <summary>
                /// Writes details for the various operation types
                /// that could be contained in the deployment plan.
                /// Optionally writes script bodies, depending on
                /// the value of the IncludeScripts property.
                /// </summary>
                private void ReportPlanOperations(XmlWriter xmlw)
                {
                }
    
                /// <summary>
                /// Returns the category of the specified element
                /// in the source model
                /// </summary>
                private string GetElementCategory(IModelElement element)
                {
                }
    
                /// <summary>
                /// Returns the name of the specified element
                /// in the source model
                /// </summary>
                private string GetElementName(IModelElement element)
                {
                }
            }
    
    ''' <summary>
    ''' This class is used to generate a deployment
    ''' report. 
    ''' </summary>
    Private Class DeploymentReportWriter
    
        Public Sub New(ByVal context As DeploymentPlanContributorContext)
        End Sub
    
        Private _includeScripts As Boolean
        ''' <summary>
        ''' Property indicating whether script bodies
        ''' should be included in the report.
        ''' </summary>
        Public Property IncludeScripts() As Boolean
            Get
                IncludeScripts = _includeScripts
            End Get
            Set(ByVal value As Boolean)
                _includeScripts = value
            End Set
        End Property
    
    
        ''' <summary> 
        ''' Drives the report generation, opening files, 
        ''' writing the beginning and ending report elements, 
        ''' and calling helper methods to report on the 
        ''' plan operations. 
        ''' </summary> 
        Friend Sub WriteReport(ByVal reportFile As FileInfo)
        End Sub
    
        ''' <summary> 
        ''' Writes details for the various operation types 
        ''' that could be contained in the deployment plan. 
        ''' Optionally writes script bodies, depending on 
        ''' the value of the IncludeScripts property. 
        ''' </summary> 
        Private Sub ReportPlanOperations(ByVal xmlw As XmlWriter)
        End Sub
        ''' <summary>
        ''' Returns the category of the specified element
        ''' in the source model
        ''' </summary> 
        Private Function GetElementCategory(ByVal element As IModelElement) As String
            Return ""
        End Function
    
        ''' <summary>
        ''' Returns the name of the specified element
        ''' in the source model
        ''' </summary>
        Private Function GetElementName(ByVal element As IModelElement) As String
            Return ""
        End Function
    End Class
    
  • Salvare le modifiche a Class1.cs.

    Aggiungere quindi i membri della classe e il corpo del metodo.

Per aggiungere membri della classe

  • Nell'editor di codice aggiungere il codice seguente alla classe DeploymentReportWriter:

                readonly DataSchemaModel _sourceModel;
                readonly ModelComparisonResult _diff;
                readonly DeploymentStep _planHead;
    
            ReadOnly _sourceModel As DataSchemaModel
            ReadOnly _diff As ModelComparisonResult
            ReadOnly _planHead As DeploymentStep
    

    I tipi di interesse includono i seguenti: DataSchemaModel , ModelComparisonResult e DeploymentStep .

    Aggiungere quindi il corpo al costruttore della classe.

Per aggiungere il corpo del metodo al costruttore

  • Aggiungere il codice seguente come corpo del costruttore:

                    if (context == null)
                    {
                        throw new ArgumentNullException("context");
                    }
    
                    // save the source model, source/target differences,
                    // and the beginning of the deployment plan.
                    _sourceModel = context.Source;
                    _diff = context.ComparisonResult;
                    _planHead = context.PlanHandle.Head;
    
                If context Is Nothing Then
                    Throw New ArgumentNullException("context")
                End If
    
                ' save the source model, source/target differences, 
                ' and the beginning of the deployment plan. 
                _sourceModel = context.Source
                _diff = context.ComparisonResult
                _planHead = context.PlanHandle.Head
    

    Aggiungere quindi il corpo del metodo al metodo WriteReport.

Per aggiungere il corpo del metodo WriteReport

  • Aggiungere il seguente codice come corpo del metodo WriteReport:

                    // Assumes that we have a valid report file
                    if (reportFile == null)
                    {
                        throw new ArgumentNullException("reportFile");
                    }
    
                    // set up the XML writer
                    XmlWriterSettings xmlws = new XmlWriterSettings();
                    // Indentation makes it a bit more readable
                    xmlws.Indent = true;
                    FileStream fs = new FileStream(reportFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    XmlWriter xmlw = XmlWriter.Create(fs, xmlws);
    
                    try
                    {
                        xmlw.WriteStartDocument(true);
                        xmlw.WriteStartElement("DeploymentReport");
    
                        // Summary report of the operations that
                        // are contained in the plan.
                        ReportPlanOperations(xmlw);
    
                        // You could add a method call here
                        // to produce a detailed listing of the 
                        // differences between the source and
                        // target model.
                        xmlw.WriteEndElement();
                        xmlw.WriteEndDocument();
                        xmlw.Flush();
                        fs.Flush();
                    }
                    finally
                    {
                        xmlw.Close();
                        fs.Dispose();
                    }
    
                ' Assumes that we have a valid report file 
                If reportFile Is Nothing Then
                    Throw New ArgumentNullException("reportFile")
                End If
    
                ' set up the XML writer 
                Dim xmlws As New XmlWriterSettings()
                ' Indentation makes it a bit more readable 
                xmlws.Indent = True
                Dim fs As New FileStream(reportFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)
                Dim xmlw As XmlWriter = XmlWriter.Create(fs, xmlws)
    
                Try
                    xmlw.WriteStartDocument(True)
                    xmlw.WriteStartElement("DeploymentReport")
    
                    ' Summary report of the operations that 
                    ' are contained in the plan. 
                    ReportPlanOperations(xmlw)
    
                    ' You could add a method call here 
                    ' to produce a detailed listing of the 
                    ' differences between the source and 
                    ' target model. 
                    xmlw.WriteEndElement()
                    xmlw.WriteEndDocument()
                    xmlw.Flush()
                    fs.Flush()
                Finally
                    xmlw.Close()
                    fs.Dispose()
                End Try
    

    I tipi di interesse sono XmlWriter e XmlWriterSettings.

    Aggiungere quindi il corpo al metodo ReportPlanOperations.

Per aggiungere il corpo del metodo al metodo ReportPlanOperations.

  • Aggiungere il seguente codice come corpo del metodo ReportPlanOperations:

                    // write the node to indicate the start
                    // of the list of operations.
                    xmlw.WriteStartElement("Operations");
    
                    // Loop through the steps in the plan,
                    // starting at the beginning.
                    DeploymentStep currentStep = _planHead;
                    while (currentStep != null)
                    {
                        // Report the type of step
                        xmlw.WriteStartElement(currentStep.GetType().Name);
    
                        // based on the type of step, report
                        // the relevant information.
                        // Note that this procedure only handles 
                        // a subset of all step types.
                        if (currentStep is SqlRenameStep)
                        {
                            SqlRenameStep renameStep = (SqlRenameStep)currentStep;
                            xmlw.WriteAttributeString("OriginalName", renameStep.OldName);
                            xmlw.WriteAttributeString("NewName", renameStep.NewName);
                            xmlw.WriteAttributeString("Category", GetElementCategory(renameStep.RenamedElement));
                        }
                        else if (currentStep is SqlMoveSchemaStep)
                        {
                            SqlMoveSchemaStep moveStep = (SqlMoveSchemaStep)currentStep;
                            xmlw.WriteAttributeString("OrignalName", moveStep.PreviousName);
                            xmlw.WriteAttributeString("NewSchema", moveStep.NewSchema);
                            xmlw.WriteAttributeString("Category", GetElementCategory(moveStep.MovedElement));
                        }
                        else if (currentStep is SqlTableMigrationStep)
                        {
                            SqlTableMigrationStep dmStep = (SqlTableMigrationStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(dmStep.SourceTable));
                            xmlw.WriteAttributeString("Category", GetElementCategory(dmStep.SourceElement));
                        }
                        else if (currentStep is CreateElementStep)
                        {
                            CreateElementStep createStep = (CreateElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(createStep.SourceElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(createStep.SourceElement));
                        }
                        else if (currentStep is AlterElementStep)
                        {
                            AlterElementStep alterStep = (AlterElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(alterStep.SourceElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(alterStep.SourceElement));
                        }
                        else if (currentStep is DropElementStep)
                        {
                            DropElementStep dropStep = (DropElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(dropStep.TargetElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(dropStep.TargetElement));
                        }
    
                        // If the script bodies are to be included,
                        // add them to the report.
                        if (this.IncludeScripts)
                        {
                            string tsqlBody = currentStep.Action();
                            if (string.IsNullOrEmpty(tsqlBody) == false)
                            {
                                xmlw.WriteCData(tsqlBody);
                            }
                        }
    
                        // close off the current step
                        xmlw.WriteEndElement();
                        currentStep = currentStep.Next;
                    }
                    xmlw.WriteEndElement();
    
                ' write the node to indicate the start 
                ' of the list of operations. 
                xmlw.WriteStartElement("Operations")
    
                ' Loop through the steps in the plan, 
                ' starting at the beginning. 
                Dim currentStep As DeploymentStep = _planHead
                While currentStep IsNot Nothing
                    ' Report the type of step 
                    xmlw.WriteStartElement(currentStep.[GetType]().Name)
    
                    ' based on the type of step, report 
                    ' the relevant information. 
                    If TypeOf currentStep Is SqlRenameStep Then
                        Dim renameStep As SqlRenameStep = DirectCast(currentStep, SqlRenameStep)
                        xmlw.WriteAttributeString("OriginalName", renameStep.OldName)
                        xmlw.WriteAttributeString("NewName", renameStep.NewName)
                        xmlw.WriteAttributeString("Category", GetElementCategory(renameStep.RenamedElement))
                    ElseIf TypeOf currentStep Is SqlMoveSchemaStep Then
                        Dim moveStep As SqlMoveSchemaStep = DirectCast(currentStep, SqlMoveSchemaStep)
                        xmlw.WriteAttributeString("OrignalName", moveStep.PreviousName)
                        xmlw.WriteAttributeString("NewSchema", moveStep.NewSchema)
                        xmlw.WriteAttributeString("Category", GetElementCategory(moveStep.MovedElement))
                    ElseIf TypeOf currentStep Is SqlTableMigrationStep Then
                        Dim dmStep As SqlTableMigrationStep = DirectCast(currentStep, SqlTableMigrationStep)
                        xmlw.WriteAttributeString("Name", GetElementName(dmStep.SourceTable))
                        xmlw.WriteAttributeString("Category", GetElementCategory(dmStep.SourceElement))
                    ElseIf TypeOf currentStep Is CreateElementStep Then
                        Dim createStep As CreateElementStep = DirectCast(currentStep, CreateElementStep)
                        xmlw.WriteAttributeString("Name", GetElementName(createStep.SourceElement))
                        xmlw.WriteAttributeString("Category", GetElementCategory(createStep.SourceElement))
                    ElseIf TypeOf currentStep Is AlterElementStep Then
                        Dim alterStep As AlterElementStep = DirectCast(currentStep, AlterElementStep)
                        xmlw.WriteAttributeString("Name", GetElementName(alterStep.SourceElement))
                        xmlw.WriteAttributeString("Category", GetElementCategory(alterStep.SourceElement))
                    ElseIf TypeOf currentStep Is DropElementStep Then
                        Dim dropStep As DropElementStep = DirectCast(currentStep, DropElementStep)
                        xmlw.WriteAttributeString("Name", GetElementName(dropStep.TargetElement))
                        xmlw.WriteAttributeString("Category", GetElementCategory(dropStep.TargetElement))
                    End If
    
                    ' If the script bodies are to be included, 
                    ' add them to the report. 
                    If Me.IncludeScripts Then
                        Dim tsqlBody As String = currentStep.Action()
                        If String.IsNullOrEmpty(tsqlBody) = False Then
                            xmlw.WriteCData(tsqlBody)
                        End If
                    End If
    
                    ' close off the current step 
                    xmlw.WriteEndElement()
                    currentStep = currentStep.[Next]
                End While
                xmlw.WriteEndElement()
    

    I tipi di interesse includono i seguenti: DeploymentStep , SqlRenameStep , SqlMoveSchemaStep , SqlTableMigrationStep , CreateElementStep , AlterElementStep e DropElementStep. I tipi di passaggi seguenti sono quelli aggiuntivi che non vengono illustrati in questo esempio: BeginPostDeploymentScriptStep , BeginPreDeploymentScriptStep , DeploymentScriptDomStep , DeploymentScriptStep , EndPostDeploymentScriptStep e EndPreDeploymentScriptStep. È inoltre possibile cercare i passaggi specifici di SQL Server: SqlBeginAltersStep , SqlBeginDropsStep , SqlBeginPreservationStep , SqlBeginTransactionStep , SqlEndAltersStep , SqlEndDropsStep , SqlEndPreservationStep , SqlEndTransactionStep , SqlFinalizeDatabaseAccessStep , SqlMoveSchemaStep , SqlPrintStep , SqlRenameStep e SqlTableMigrationStep.

    Aggiungere quindi il corpo del metodo GetElementCategory.

Per aggiungere il corpo del metodo al metodo GetElementCategory.

  • Aggiungere il seguente codice come corpo del metodo GetElementCategory:

                    return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementTypeDescription(
                        element.ElementClass);
    
                Return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementTypeDescription(element.ElementClass)
    

    Tipi e metodi di interesse includono i seguenti: DataSchemaModel , DatabaseSchemaProvider , UserInteractionServices e GetElementTypeDescription.

    Aggiungere quindi il corpo del metodo GetElementName.

Per aggiungere il corpo del metodo al metodo GetElementName.

  • Aggiungere il seguente codice come corpo del metodo GetElementName:

                    return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementName(
                        element, 
                        ElementNameStyle.FullyQualifiedName);
    
                Return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementName(element, ElementNameStyle.FullyQualifiedName)
    

    Tipi e metodi di interesse includono i seguenti: DataSchemaModel , DatabaseSchemaProvider , UserInteractionServices , GetElementName e ElementNameStyle.

    Salvare le modifiche alla classe. Compilare quindi la libreria di classi.

Per firmare e compilare l'assembly

  1. Scegliere Proprietà di MyDeploymentContributor dal menu Progetto.

  2. Fare clic sulla scheda Firma.

  3. Fare clic su Firma assembly.

  4. In Scegli un file chiave con nome sicuro fare clic su <Nuovo>.

  5. Nella finestra di dialogo Crea chiave con nome sicuro digitare MyRefKey nel campo Nome file di chiave.

  6. (Facoltativo) È possibile specificare una password per il file di chiave con nome sicuro.

  7. Scegliere OK.

  8. Scegliere Salva tutto dal menu File.

  9. Scegliere Compila soluzione dal menu Compila.

    Sarà quindi necessario installare e registrare l'assembly in modo che venga caricato quando si distribuiscono progetti di database.

Installare un collaboratore alla distribuzione

Per installare un collaboratore alla distribuzione, è necessario effettuare le attività seguenti:

  • Copiare l'assembly e il file con estensione pdb associato nella cartella Extensions

  • Creare un file Extensions.xml per registrare il collaboratore alla distribuzione in modo che venga caricato quando si distribuiscono i progetti di database

Per installare l'assembly MyDeploymentContributor

  1. Creare una cartella denominata MyExtensions nella cartella %Programmi%\Microsoft Visual Studio 10.0\VSTSDB\Extensions.

  2. Copiare l'assembly firmato (MyDeploymentContributor.dll) e il file con estensione pdb associato (MyDeploymentContributor.pdb) nella cartella %Programmi%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions.

    Nota

    Si consiglia di non copiare i file XML direttamente nella cartella %Programmi%\Microsoft Visual Studio 10.0\VSTSDB\Extensions. Se si utilizza una sottocartella, si eviterà che vengano apportate modifiche accidentali agli altri file forniti con Visual Studio Premium.

    Sarà quindi necessario registrare l'assembly, che è un tipo di estensione di funzionalità, in modo che venga visualizzato in Visual Studio Premium.

Per registrare l'assembly MyDeploymentContributor

  1. Scegliere Altre finestre dal menu Visualizza, quindi fare clic su Finestra di comando per aprire la finestra Comando.

  2. Nella finestra Comando digitare il codice seguente. Sostituire FilePath con il percorso e il nome del file con estensione dll compilato. Racchiudere il percorso e il nome del file tra virgolette.

    Nota

    Per impostazione predefinita, il percorso del file con estensione dll compilato è PercorsoSoluzione\bin\Debug o PercorsoSoluzione\bin\Release.

    ? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
    
    ? System.Reflection.Assembly.LoadFrom("FilePath").FullName
    
  3. Premere Invio.

  4. Copiare negli Appunti la riga risultante, che dovrebbe essere simile alla seguente:

    "MyDeploymentContributor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
    
  5. Aprire un editor di testo, ad esempio Blocco note.

    Nota importanteImportante

    In Windows Vista e Microsoft Windows Server 2008 aprire l'editor come amministratore in modo che sia possibile salvare il file nella cartella Programmi.

  6. Fornire le seguenti informazioni specificando il nome dell'assembly personale, il token di chiave pubblica e il tipo di estensione:

    <?xml version="1.0" encoding="utf-8" ?> 
    <extensions assembly="" version="1" xmlns="urn:Microsoft.Data.Schema.Extensions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:Microsoft.Data.Schema.Extensions Microsoft.Data.Schema.Extensions.xsd">
      <extension type="MyDeploymentContributor.DeploymentUpdateReportContributor" 
    assembly="MyDeploymentContributor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<enter key here>" enabled="true" />
    </extensions>
    

    Questo file XML viene utilizzato per registrare la classe che eredita da DeploymentPlanExecutor.

  7. Salvare il file con il nome MyDeploymentContributor.extensions.xml nella cartella %Programmi%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions.

  8. Chiudere Visual Studio.

    Si distribuirà quindi un progetto di database per testare il collaboratore.

Testare il collaboratore alla distribuzione

Per testare il collaboratore alla distribuzione, è necessario effettuare le attività seguenti:

  • Aggiungere una proprietà al file con estensione dbproj che si prevede di distribuire

  • Distribuire il progetto di database tramite MSBuild e fornendo il parametro adatto

Aggiungere proprietà al file del progetto di database (con estensione dbproj).

Se si desidera utilizzare questo collaboratore alla distribuzione da MSBuild, è necessario modificare il progetto di database per consentire agli utenti di passare un parametro tramite MSBuild. Per aggiornare il progetto di database, aprirlo nell'editor desiderato e aggiungere le istruzioni seguenti al file con estensione dbproj, tra l'ultimo nodo </ItemGroup> nel file e il nodo </Project> finale:

  <ItemGroup>
    <DeploymentContributorArgument Include="GenerateUpdateReport=$(GenerateUpdateReport)" />
  </ItemGroup>

Dopo avere aggiornato il file con estensione dbproj, è possibile utilizzare MSBuild per passare parametri per le compilazioni da riga di comando.

Distribuire il progetto di database

Per distribuire il progetto di database e generare un rapporto di distribuzione

  1. Aprire un prompt dei comandi di Visual Studio. Fare clic sul pulsante Start, scegliere Tutti i programmi, quindi Microsoft Visual Studio 2010, Visual Studio Tools e fare clic su Prompt dei comandi di Visual Studio 2010.

  2. Al prompt dei comandi individuare la cartella che contiene il progetto di database.

  3. Al prompt dei comandi digitare la riga di comando seguente:

    MSBuild /t:Rebuild MyDatabaseProject.dbproj /p:OutDir=.\
    

    Sostituire MyDatabaseProject con il nome del progetto di database che si desidera compilare. Se il progetto fosse stato modificato dopo l'ultima compilazione, è possibile utilizzare /t:Build anziché /t:Rebuild.

  4. Al prompt dei comandi digitare la riga di comando seguente:

    MSBuild /t:Deploy MyDatabaseProject.dbproj /p:GenerateUpdateReport=true
    

    Sostituire MyDatabaseProject con il nome del progetto di database che si desidera distribuire.

    Verrà visualizzato un output analogo al seguente:

Microsoft (R) Build Engine Version 4.0.20817.0
[Microsoft .NET Framework, Version 4.0.20817.0]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 8/26/2009 3:12:43 PM.
Project "C:\Users\UserName\Documents\Visual Studio 2010\Projects\MyDatabaseProject\Dep
TestToo\MyDatabaseProject.dbproj" on node 1 (Deploy target(s)).
DspDeploy:
  GenerateUpdateReport=true

  Deployment reports ->
  C:\Users\UserName\Documents\Visual Studio 2010\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.summary.xml
  C:\Users\UserName\Documents\Visual Studio 2010\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.details.xml

  Deployment script generated to:
  C:\Users\UserName\Documents\Visual Studio 2010\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyDatabaseProject.sql

Done Building Project "C:\Users\UserName\Documents\Visual Studio 2010\Projects\MyDatabaseProject\MyDatabaseProject\MyDatabaseProject.dbproj" (Deploy target(s)).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.02
  1. Aprire MyTargetDatabase.summary.xml ed esaminare il contenuto.

    Il file è simile all'esempio seguente che mostra una nuova distribuzione del database:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<DeploymentReport>
  <Operations>
    <DeploymentScriptStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptStep />
    <DeploymentScriptStep />
    <DeploymentScriptStep />
    <DeploymentScriptStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptStep />
    <DeploymentScriptDomStep />
    <BeginPreDeploymentScriptStep />
    <DeploymentScriptStep />
    <EndPreDeploymentScriptStep />
    <SqlBeginPreservationStep />
    <SqlEndPreservationStep />
    <SqlBeginDropsStep />
    <SqlEndDropsStep />
    <SqlBeginAltersStep />
    <SqlPrintStep />
    <CreateElementStep Name="Sales" Category="Schema" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Customer" Category="Table" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.PK_Customer_CustID" Category="Primary Key" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Orders" Category="Table" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.PK_Orders_OrderID" Category="Primary Key" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Def_Customer_YTDOrders" Category="Default Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Def_Customer_YTDSales" Category="Default Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Def_Orders_OrderDate" Category="Default Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.Def_Orders_Status" Category="Default Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.FK_Orders_Customer_CustID" Category="Foreign Key" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.CK_Orders_FilledDate" Category="Check Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.CK_Orders_OrderDate" Category="Check Constraint" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.uspCancelOrder" Category="Procedure" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.uspFillOrder" Category="Procedure" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.uspNewCustomer" Category="Procedure" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.uspPlaceNewOrder" Category="Procedure" />
    <SqlPrintStep />
    <CreateElementStep Name="Sales.uspShowOrderDetails" Category="Procedure" />
    <SqlEndAltersStep />
    <DeploymentScriptStep />
    <BeginPostDeploymentScriptStep />
    <DeploymentScriptStep />
    <EndPostDeploymentScriptStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptDomStep />
    <DeploymentScriptDomStep />
  </Operations>
</DeploymentReport>

Nota

Se si distribuisce un progetto di database identico al database di destinazione, il rapporto risultante non sarà molto significativo. Per risultati più significativi, distribuire le modifiche a un database o distribuisce un nuovo database.

  1. Aprire MyTargetDatabase.details.xml ed esaminare il contenuto.

    In una piccola sezione del file di dettagli sono riportate le voci e lo script che creano lo schema Sales, che stampa un messaggio sulla creazione di una tabella e crea la tabella:

    <CreateElementStep Name="Sales" Category="Schema"><![CDATA[CREATE SCHEMA [Sales]
    AUTHORIZATION [dbo];

]]></CreateElementStep>
    <SqlPrintStep><![CDATA[PRINT N'Creating [Sales].[Customer]...';

]]></SqlPrintStep>
    <CreateElementStep Name="Sales.Customer" Category="Table"><![CDATA[CREATE TABLE [Sales].[Customer] (
    [CustomerID]   INT           IDENTITY (1, 1) NOT NULL,
    [CustomerName] NVARCHAR (40) NOT NULL,
    [YTDOrders]    INT           NOT NULL,
    [YTDSales]     INT           NOT NULL
);

]]></CreateElementStep>

Analizzando il piano di distribuzione mentre viene eseguito, sarà possibile creare rapporti su qualsiasi informazione contenuta nella distribuzione e intraprendere azioni aggiuntive in base ai passaggi contenuti in tale piano.

Passaggi successivi

È possibile creare strumenti aggiuntivi per eseguire l'elaborazione dei file XML di output. Si tratta di solo uno esempio di un oggetto DeploymentPlanExecutor. È inoltre possibile creare un oggetto DeploymentPlanModifier per modificare un piano di distribuzione prima che venga eseguito.

Vedere anche

Concetti

Estensione delle funzionalità di database di Visual Studio

Altre risorse

Personalizzare compilazione e distribuzione del database tramite collaboratori alla compilazione e distribuzione

Procedura dettagliata: estendere la compilazione del progetto di database per generare statistiche dal modello

Procedura dettagliata: estendere la distribuzione del progetto di database per modificare il piano di distribuzione