Compartir a través de


Tutorial: Extender la implementación del proyecto de base de datos para analizar el plan de implementación

Puede crear colaboradores de implementación para realizar acciones personalizadas cuando implemente un proyecto de base de datos. Puede crear un DeploymentPlanModifier o un DeploymentPlanExecutor. Utilice un DeploymentPlanModifier para cambiar el plan antes de su ejecución y un DeploymentPlanExecutor para realizar operaciones mientras se ejecuta el plan. En este tutorial creará un DeploymentPlanExecutor denominado DeploymentUpdateReportContributor que crea un informe sobre las acciones que se realizan al implementar un proyecto de base de datos. Dado que este colaborador de compilación acepta un parámetro para controlar si se genera el informe, debe realizar un paso obligatorio adicional.

En este tutorial llevará a cabo las siguientes tareas principales:

  • Crear el tipo DeploymentPlanExecutor de colaborador de implementación

  • Instalar el colaborador de implementación

  • Probar su colaborador de implementación

Requisitos previos

Necesita los componentes siguientes para completar este tutorial:

  • Tener Visual Studio 2010 Premium o Visual Studio 2010 Ultimate instalado en el equipo.

  • Un proyecto de base de datos que contenga objetos de base de datos.

  • Una instancia de SQL Server en la que pueda implementar un proyecto de base de datos.

Nota

Este tutorial está dirigido a los usuarios que ya están familiarizados con las características de base de datos de Visual Studio. También se espera que esté familiarizado con los conceptos básicos de Visual Studio, como, por ejemplo, la forma de crear una biblioteca de clases y de usar el editor de código para agregar código a una clase.

Crear un colaborador de implementación

Para crear un colaborador de implementación, debe realizar las siguientes tareas:

  • Crear un proyecto de biblioteca de clases y agregar las referencias necesarias

  • Definir una clase denominada DeploymentUpdateReportContributor que herede de DeploymentPlanExecutor

  • Reemplazar los métodos OnExecute y OnPopulateArguments

  • Agregar una clase auxiliar privada

  • Compilar el ensamblado resultante

Para crear un proyecto de biblioteca de clases

  1. Cree un proyecto de biblioteca de clases de Visual Basic o Visual C# denominado MyDeploymentContributor.

  2. En el Explorador de soluciones, haga clic con el botón secundario en la carpeta Referencias y haga clic en Agregar referencia.

  3. Haga clic en la ficha .NET.

  4. Resalte las entradas Microsoft.Data.Schema.Sql y Microsoft.Data.Schema y haga clic en Aceptar.

    A continuación, comience a agregar código a la clase.

Para definir la clase DeploymentUpdateReportContributor

  1. En el editor de código, actualice el archivo class1.cs para que coincida con las siguientes instrucciones 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. Actualice la definición de clase para que coincida con la siguiente:

        [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
    

    Ahora ha definido su colaborador de compilación y ha utilizado el atributo para indicar que este colaborador es compatible con cualquier proveedor de esquemas de base de datos que herede de SqlDatabaseSchemaProvider.

  3. A continuación, agregue el siguiente miembro que utilizará para permitir que este proveedor acepte un parámetro de línea de comandos:

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

    Este miembro le permite especificar si el informe se debería generar mediante la opción GenerateUpdateReport.

    A continuación, reemplace el método OnPopulateArguments para compilar la lista de argumentos que se va a pasar al colaborador de implementación.

Para reemplazar OnPopulateArguments

  • Agregue el siguiente método de reemplazo a la clase DeploymentUpdateReportContributor:

        /// <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
    

    Compile un objeto ContributorArgumentConfiguration y agréguelo a la lista de argumentos. De forma predeterminada, se genera el informe al generar una compilación de depuración.

    A continuación, reemplace el método OnExecute para agregar el código que desea que se ejecute cuando se implemente un proyecto de base de datos.

Para reemplazar OnExecute

  • Agregue el siguiente método a su clase DeploymentUpdateReportContributor:

        /// <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
    

    Se pasa un objeto DeploymentPlanContributorContext que proporciona acceso a cualquier argumento especificado, el modelo de base de datos de origen y destino, propiedades de compilación y archivos de extensión al método OnExecute. En este ejemplo, obtenemos el modelo y, a continuación, llamamos a las funciones auxiliares para generar información sobre el modelo. También se pasa un objeto ErrorManager al método para utilizarlo para notificar cualquier error que se produzca.

    Los tipos y métodos adicionales de interés incluyen: DataSchemaModel, ModelStore, ModelComparisonResult, DatabaseSchemaProvider, DeploymentPlanHandle y SchemaDeploymentOptions.

    A continuación, defina la clase auxiliar que profundiza en los detalles del plan de implementación.

Para agregar la clase auxiliar que genera el cuerpo del informe

  • Primero, agregue los esqueletos de la clase auxiliar y sus métodos agregando el siguiente código:

            /// <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
    
  • Guarde los cambios en Class1.cs.

    A continuación, agregará los miembros de clase y los cuerpos de método.

Para agregar los miembros de la clase

  • En el editor de código, agregue el siguiente código a la clase DeploymentReportWriter:

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

    Los tipos de interés incluyen: DataSchemaModel, ModelComparisonResult y DeploymentStep.

    A continuación, agregue el cuerpo al constructor de clase.

Para agregar el cuerpo del método al constructor

  • Agregue el siguiente código como cuerpo del constructor:

                    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
    

    A continuación, agregue el cuerpo del método al método WriteReport.

Para agregar el cuerpo del método al método WriteReport

  • Agregue el siguiente código como cuerpo del método 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
    

    Los tipos de interés son XmlWriter y XmlWriterSettings.

    A continuación, agregue el cuerpo al método ReportPlanOperations.

Para agregar el cuerpo al método ReportPlanOperations

  • Agregue el siguiente código como cuerpo del método 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()
    

    Los tipos de interés incluyen: DeploymentStep, SqlRenameStep, SqlMoveSchemaStep, SqlTableMigrationStep, CreateElementStep, AlterElementStep y DropElementStep. Los siguientes tipos de paso son tipos de paso adicionales que no se muestran en este ejemplo: BeginPostDeploymentScriptStep, BeginPreDeploymentScriptStep, DeploymentScriptDomStep, DeploymentScriptStep, EndPostDeploymentScriptStep y EndPreDeploymentScriptStep. También podría buscar los pasos específicos de SQL Server: SqlBeginAltersStep, SqlBeginDropsStep, SqlBeginPreservationStep, SqlBeginTransactionStep, SqlEndAltersStep, SqlEndDropsStep, SqlEndPreservationStep, SqlEndTransactionStep, SqlFinalizeDatabaseAccessStep, SqlMoveSchemaStep, SqlPrintStep, SqlRenameStep y SqlTableMigrationStep.

    A continuación, agregue el cuerpo del método GetElementCategory.

Para agregar el cuerpo al método GetElementCategory

  • Agregue el siguiente código como cuerpo del método GetElementCategory:

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

    Los tipos y métodos de interés incluyen: DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices y GetElementTypeDescription.

    A continuación, agregue el cuerpo del método GetElementName.

Para agregar el cuerpo del método al método GetElementName

  • Agregue el siguiente código como cuerpo del método GetElementName:

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

    Los tipos y métodos de interés incluyen: DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices, GetElementName y ElementNameStyle.

    Guarde los cambios en la clase. A continuación, compile la biblioteca de clases.

Para firmar y compilar el ensamblado

  1. En el menú Proyecto, haga clic en Propiedades de MyDeploymentContributor.

  2. Haga clic en la ficha Firma.

  3. Haga clic en Firmar el ensamblado.

  4. En Elija un archivo de clave de nombre seguro, haga clic en <Nuevo>.

  5. En el cuadro de diálogo Crear clave de nombre seguro, en Nombre del archivo de clave, escriba MyRefKey.

  6. (opcional) Puede especificar una contraseña para el archivo de clave de nombre seguro.

  7. Haga clic en Aceptar.

  8. En el menú Archivo, haga clic en Guardar todo.

  9. En el menú Generar, haga clic en Generar solución.

    Después, debe instalar y registrar el ensamblado para que se cargue al implementar proyectos de base de datos.

Instalar un colaborador de implementación

Para instalar un colaborador de implementación, debe realizar las siguientes tareas:

  • Copiar el ensamblado y el archivo .pdb asociado en la carpeta Extensions

  • Crear un archivo Extensions.xml para registrar el colaborador de implementación para que se cargue al implementar proyectos de base de datos

Para instalar el ensamblado MyDeploymentContributor

  1. Cree una carpeta denominada MyExtensions en la carpeta %Archivos de programa%\Microsoft Visual Studio 10.0\VSTSDB\Extensions.

  2. Copie el ensamblado firmado (MyDeploymentContributor.dll) y el archivo .pdb asociado (MyDeploymentContributor.pdb) a la carpeta %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions.

    Nota

    Se recomienda no copiar directamente los archivos XML a la carpeta %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions. Si usa una subcarpeta en su lugar, evitará cambios accidentales en los demás archivos proporcionados con Visual Studio Premium.

    A continuación, debe registrar el ensamblado, que es un tipo de extensión de características, para que aparezca en Visual Studio Premium.

Para registrar el ensamblado MyDeploymentContributor

  1. En el menú Ver, haga clic en Otras ventanas y, a continuación, haga clic en Ventana Comandos para abrir la ventana Comando.

  2. En la ventana Comando, escriba el código siguiente. En FilePath, sustituya la ruta de acceso y el nombre de archivo por la ruta y el nombre de su archivo .dll compilado. Debe escribir la ruta de acceso y el nombre de archivo entre comillas.

    Nota

    De forma predeterminada, la ruta de acceso del archivo .dll compilado es rutaDeAccesoDeSolución\bin\Debug o rutaDeAccesoDeSolución\bin\Release.

    ? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
    
    ? System.Reflection.Assembly.LoadFrom("FilePath").FullName
    
  3. Presione Entrar.

  4. Copie la línea resultante al Portapapeles. Debe ser similar a la siguiente:

    "MyDeploymentContributor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
    
  5. Abra un editor de texto sin formato, como el Bloc de notas.

    Nota importanteImportante

    En Windows Vista y Microsoft Windows Server 2008, abra el editor como administrador para que pueda guardar el archivo en su carpeta Archivos de programa.

  6. Proporcione la siguiente información, especificando el nombre del ensamblado, el símbolo de clave pública y el tipo de extensión:

    <?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>
    

    Utilice este archivo XML para registrar la clase que hereda de DeploymentPlanExecutor.

  7. Guarde el archivo como MyDeploymentContributor.extensions.xml en la carpeta %Archivos de programa%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions.

  8. Cierre Visual Studio.

    A continuación, implementará un proyecto de base de datos para probar su colaborador.

Probar su colaborador de implementación

Para probar su colaborador de implementación, debe realizar las siguientes tareas:

  • Agregar una propiedad al archivo .dbproj que piensa implementar

  • Implementar el proyecto de base de datos utilizando MSBuild y proporcionando el parámetro adecuado

Agregar propiedades al archivo de proyecto de base de datos (.dbproj)

Si desea utilizar este colaborador de implementación de MSBuild, debe modificar el proyecto de base de datos para permitir a los usuarios pasar un parámetro a través de MSBuild. Para actualizar el proyecto de base de datos, ábralo en el editor que desee y agregue las siguientes instrucciones al archivo .dbproj entre el último nodo </ItemGroup> del archivo y el nodo </Project> final:

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

Después de haber actualizado el archivo .dbproj, puede usar MSBuild para pasar los parámetros de las compilaciones de línea de comandos.

Implementar el proyecto de base de datos

Para implementar su proyecto de base de datos y generar un informe de implementación

  1. Abra un símbolo del sistema de Visual Studio. En el menú Iniciar, haga clic en Todos los programas, en Microsoft Visual Studio 2010, en Visual Studio Tools y, a continuación, en Símbolo del sistema de Visual Studio (2010).

  2. En el símbolo del sistema, navegue a la carpeta que contiene el proyecto de base de datos.

  3. En el símbolo del sistema, escriba la siguiente línea de comandos:

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

    Sustituya MyDatabaseProject por el nombre del proyecto de base de datos que desea compilar. Si hubiera cambiado el proyecto después de compilarlo por última vez, podría utilizar /t:Build en lugar de /t:Rebuild.

  4. En el símbolo del sistema, escriba la siguiente línea de comandos:

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

    Sustituya MyDatabaseProject por el nombre del proyecto de base de datos que desea implementar.

    Aparecen resultados como los siguientes:

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. Abra MyTargetDatabase.summary.xml y examine el contenido.

    El archivo se parece al siguiente ejemplo que muestra una nueva implementación de base de datos:

<?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

Si implementa un proyecto de base de datos que sea idéntico a la base de datos de destino, el informe resultante no será muy significativo. Para obtener resultados más significativos, implemente los cambios en una base de datos o implemente una nueva base de datos.

  1. Abra MyTargetDatabase.details.xml y examine el contenido.

    Una pequeña sección del archivo de detalles muestra las entradas y el script que crean el esquema Sales, que imprime un mensaje sobre la creación de una tabla y la crea:

    <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>

Si analiza el plan de implementación a medida que se ejecuta, puede notificar cualquier información incluida en la implementación y tomar las medidas adicionales basadas en los pasos de ese plan.

Pasos siguientes

Podría crear herramientas adicionales para realizar el procesamiento de los archivos XML de resultados. Éste es simplemente un ejemplo de un DeploymentPlanExecutor. También podría crear un DeploymentPlanModifier para cambiar un plan de implementación antes de su ejecución.

Vea también

Conceptos

Extender las características de base de datos de Visual Studio

Otros recursos

Personalizar la compilación e implementación de bases de datos mediante colaboradores de compilación e implementación

Tutorial: Extender la compilación del proyecto de base de datos para generar estadísticas del modelo

Tutorial: Extender la implementación del proyecto de base de datos para modificar el plan de implementación