Tutorial: Extensión de 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 al implementar un proyecto de SQL. Puede crear un DeploymentPlanModifier o un DeploymentPlanExecutor. Use un DeploymentPlanModifier para cambiar el plan antes de que se ejecute 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 otro paso necesario.

En este tutorial, se realizan las siguientes tareas principales:

Prerrequisitos

Necesitará los componentes siguientes para completar este tutorial:

  • Debe haber instalado una versión de Visual Studio que incluya SQL Server Data Tools (SSDT) y admita el desarrollo de C# o VB.
  • Debe tener un proyecto SQL que contenga objetos SQL.
  • Instancia de SQL Server en la que puede implementar un proyecto de base de datos.

Nota:

Este tutorial está diseñado para los usuarios que ya están familiarizados con las características sql de SSDT. También se espera que esté familiarizado con los conceptos básicos de Visual Studio, como cómo crear una biblioteca de clases y cómo usar el editor de código para agregar código a una clase.

Creación de un colaborador de implementación

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

  • Cree un proyecto de biblioteca de clases y agregue referencias necesarias.

  • Defina una clase denominada DeploymentUpdateReportContributor que herede de DeploymentPlanExecutor.

  • Invalide el método OnExecute.

  • Agregue una clase auxiliar privada.

  • Compile el ensamblado resultante.

Creación de un proyecto de biblioteca de clases

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

  2. Cambie el nombre del archivo "Class1.cs" a "DeploymentUpdateReportContributor.cs".

  3. En el Explorador de soluciones, haga clic con el botón derecho en el nodo del proyecto y seleccione Agregar referencia.

  4. Seleccione System.ComponentModel.Composition en la pestaña Marcos.

  5. Agregar referencias SQL necesarias: haga clic con el botón derecho en el nodo del proyecto y seleccione Agregar referencia. Seleccione Examinar y vaya a la carpeta C:\Archivos de programa (x86)\Microsoft SQL Server\110\DAC\Bin . Elija el Microsoft.SqlServer.Dac.dll, Microsoft.SqlServer.Dac.Extensions.dlly Microsoft.Data.Tools.Schema.Sql.dll entradas, seleccione Agregar y, a continuación, seleccione Aceptar.

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

Definir la clase DeploymentUpdateReportContributor

  1. En el editor de código, actualice el archivo DeploymentUpdateReportContributor.cs para hacer que coincida con las siguientes declaraciones using:

    using System;
    using System.IO;
    using System.Text;
    using System.Xml;
    using Microsoft.SqlServer.Dac.Deployment;
    using Microsoft.SqlServer.Dac.Extensibility;
    using Microsoft.SqlServer.Dac.Model;
    
  2. Actualice la definición de clase para que coincida con el código siguiente:

    /// <summary>
        /// An executor that generates a report detailing the steps in the deployment plan. Only runs if a
        /// "GenerateUpdateReport=true" contributor argument is set in the project file, in a targets file or
        /// passed as an additional argument to the DacServices API. To set in a project file, add:
        ///
        /// <PropertyGroup>
        ///     <ContributorArguments Condition="'$(Configuration)' == 'Debug'">
        /// $(ContributorArguments);DeploymentUpdateReportContributor.GenerateUpdateReport=true;
        ///     </ContributorArguments>
        /// <PropertyGroup>
        ///
        /// </summary>
        [ExportDeploymentPlanExecutor("MyDeploymentContributor.DeploymentUpdateReportContributor", "1.0.0.0")]
        public class DeploymentUpdateReportContributor : DeploymentPlanExecutor
        {
        }
    

    Ahora ha definido su componente de implementación que hereda de DeploymentPlanExecutor. Durante los procesos de compilación e implementación, los componentes personalizados se cargan desde un directorio estándar de extensiones. Los colaboradores del ejecutor del plan de implementación se identifican mediante un atributo ExportDeploymentPlanExecutor .

    Este atributo es necesario para que se puedan detectar colaboradores. Debería ser similar al código siguiente:

    [ExportDeploymentPlanExecutor("MyDeploymentContributor.DeploymentUpdateReportContributor", "1.0.0.0")]
    

    En este caso, el primer parámetro del atributo debe ser un identificador único: se usa para identificar al colaborador en los archivos del proyecto. Un procedimiento recomendado es combinar el espacio de nombres de la biblioteca, en este tutorial MyDeploymentContributor, con el nombre de clase, en este tutorial DeploymentUpdateReportContributor, para generar el identificador.

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

    public const string GenerateUpdateReport = "DeploymentUpdateReportContributor.GenerateUpdateReport";
    

    Este miembro permite al usuario especificar si se debe generar el informe mediante la opción GenerateUpdateReport.

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

Sobrescribir OnExecute

  • Agregue el método siguiente a la 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 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;
    
                ExtensibilityError reportMsg = new ExtensibilityError(msg, Severity.Message);
                base.PublishMessage(reportMsg);
            }
        /// <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 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);
            }
    

    El método OnExecute se pasa un objeto DeploymentPlanContributorContext que proporciona acceso a los argumentos especificados, el modelo de base de datos de origen y de destino, las propiedades de compilación y los archivos de extensión. En este ejemplo, obtenemos el modelo y, a continuación, llamamos a funciones auxiliares para generar información sobre el modelo. Usamos el método auxiliar PublishMessage en la clase base para notificar los errores que se producen.

    Entre los tipos y métodos adicionales de interés se incluyen: TSqlModel, ModelComparisonResult, DeploymentPlanHandle y SqlDeploymentOptions.

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

Adición de la clase auxiliar que genera el cuerpo del informe

  • Agregue la clase auxiliar y sus métodos agregando el código siguiente:

    /// <summary>
            /// This class is used to generate a deployment
            /// report.
            /// </summary>
            private class DeploymentReportWriter
            {
                readonly TSqlModel _sourceModel;
                readonly ModelComparisonResult _diff;
                readonly DeploymentStep _planHead;
    
                /// <summary>
                /// The constructor accepts the same context info
                /// that was passed to the OnExecute method of the
                /// deployment contributor.
                /// </summary>
                public DeploymentReportWriter(DeploymentPlanContributorContext context)
                {
                    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;
                }
                /// <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)
                {// 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();
                    }
                }
    
                /// <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)
                {// 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("OriginalName", 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)
                        {
                            using (StringWriter sw = new StringWriter())
                            {
                                currentStep.GenerateBatchScript(sw);
                                string tsqlBody = sw.ToString();
                                if (string.IsNullOrEmpty(tsqlBody) == false)
                                {
                                    xmlw.WriteCData(tsqlBody);
                                }
                            }
                        }
    
                        // close off the current step
                        xmlw.WriteEndElement();
                        currentStep = currentStep.Next;
                    }
                    xmlw.WriteEndElement();
                }
    
                /// <summary>
                /// Returns the category of the specified element
                /// in the source model
                /// </summary>
                private string GetElementCategory(TSqlObject element)
                {
                    return element.ObjectType.Name;
                }
    
                /// <summary>
                /// Returns the name of the specified element
                /// in the source model
                /// </summary>
                private static string GetElementName(TSqlObject element)
                {
                    StringBuilder name = new StringBuilder();
                    if (element.Name.HasExternalParts)
                    {
                        foreach (string part in element.Name.ExternalParts)
                        {
                            if (name.Length > 0)
                            {
                                name.Append('.');
                            }
                            name.AppendFormat("[{0}]", part);
                        }
                    }
    
                    foreach (string part in element.Name.Parts)
                    {
                        if (name.Length > 0)
                        {
                            name.Append('.');
                        }
                        name.AppendFormat("[{0}]", part);
                    }
    
                    return name.ToString();
                }
            }        /// <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)
                {
                }
            }
    
  • Guarde los cambios en el archivo de clase. Se hace referencia a varios tipos útiles en la clase auxiliar:

    Área de código Tipos útiles
    Miembros de clase TSqlModel, ModelComparisonResult, DeploymentStep
    Método WriteReport XmlWriter y XmlWriterSettings
    Método ReportPlanOperations Los tipos de interés incluyen: DeploymentStep, SqlRenameStep, SqlMoveSchemaStep, SqlTableMigrationStep, CreateElementStep, AlterElementStep, DropElementStep.

    Hay otros pasos: consulte la documentación de api para obtener una lista completa de los pasos.
    ObtenerCategoríaDelElemento TSqlObject
    GetElementName TSqlObject

    A continuación, compile la biblioteca de clases.

Firmar y construir el ensamblaje

  1. En el menú Proyecto, seleccione MyDeploymentContributor Properties (Propiedades de MyDeploymentContributor).

  2. Seleccione la pestaña Firma .

  3. Seleccione Firmar el ensamblado.

  4. En Elegir un archivo de clave de nombre seguro, seleccione <Nuevo>.

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

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

  7. Selecciona Aceptar.

  8. En el menú Archivo, seleccione Guardar todo.

  9. En el menú Compilar, seleccione Compilar solución.

A continuación, debe instalar el ensamblado para que se cargue cuando compile y despliegue proyectos SQL.

Instalación de un colaborador de implementación

Para instalar un colaborador de implementación, debe copiar el ensamblado y el archivo asociado .pdb a la carpeta Extensiones.

Instalación del ensamblado MyDeploymentContributor

  • A continuación, copie la información del ensamblado en el directorio de Extensiones. Cuando se inicia Visual Studio, identifica las extensiones del %ProgramFiles%\Microsoft SQL Server\110\DAC\Bin\Extensions directorio y los subdirectorios y los pone a disposición para su uso:

  • Copie el MyDeploymentContributor.dll archivo de ensamblado del directorio de salida en el %ProgramFiles%\Microsoft SQL Server\110\DAC\Bin\Extensions directorio . De forma predeterminada, la ruta de acceso del archivo compilado .dll es YourSolutionPath\YourProjectPath\bin\Debug o YourSolutionPath\YourProjectPath\bin\Release.

Prueba tu colaborador de implementación

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

  • Agregue propiedades al .sqlproj archivo que planea implementar.

  • Implemente el proyecto mediante MSBuild y proporcione el parámetro adecuado.

Agregar propiedades al archivo del proyecto SQL (.sqlproj)

Siempre debe actualizar el archivo de proyecto de SQL para especificar el ID de los colaboradores que desea incluir. Además, dado que este colaborador espera un argumento "GenerateUpdateReport", se debe especificar como un argumento del colaborador.

Puede hacerlo de una de estas dos maneras. Puede modificar manualmente el .sqlproj archivo para agregar los argumentos necesarios. Puede optar por hacerlo si el colaborador no tiene ningún argumento de colaborador necesario para la configuración o si no pretende reutilizar el colaborador en un gran número de proyectos. Si elige esta opción, agregue las siguientes instrucciones al archivo .sqlproj después del primer nodo Import del archivo.

<PropertyGroup>
    <DeploymentContributors>$(DeploymentContributors); MyDeploymentContributor.DeploymentUpdateReportContributor</DeploymentContributors>
<ContributorArguments Condition="'$(Configuration)' == 'Debug'">$(ContributorArguments);DeploymentUpdateReportContributor.GenerateUpdateReport=true;</ContributorArguments>
  </PropertyGroup>

El segundo método consiste en crear un archivo de destino que contenga los argumentos de colaborador necesarios. Esto resulta útil si usa el mismo colaborador para varios proyectos y tiene argumentos de colaborador necesarios, ya que incluye los valores predeterminados. En este caso, cree un archivo de destino en la ruta de acceso de extensiones de MSBuild.

  1. Navegue a %ProgramFiles%\MSBuild.

  2. Cree una nueva carpeta MyContributors donde se almacenen los archivos de destino.

  3. Cree un nuevo archivo MyContributors.targets dentro de este directorio, agregue el texto siguiente a él y guarde el archivo:

    <?xml version="1.0" encoding="utf-8"?>
    
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
    <DeploymentContributors>$(DeploymentContributors);MyDeploymentContributor.DeploymentUpdateReportContributor</DeploymentContributors>
    <ContributorArguments Condition="'$(Configuration)' == 'Debug'">$(ContributorArguments); DeploymentUpdateReportContributor.GenerateUpdateReport=true;</ContributorArguments>
      </PropertyGroup>
    </Project>
    
  4. Dentro del archivo .sqlproj de cualquier proyecto que desee ejecutar, importe el archivo de objetivos agregando la siguiente instrucción al archivo .sqlproj después del nodo <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" /> en el archivo:

    <Import Project="$(MSBuildExtensionsPath)\MyContributors\MyContributors.targets " />
    

Una vez que haya seguido uno de estos enfoques, puede usar MSBuild para pasar los parámetros de las compilaciones de línea de comandos.

Nota:

Siempre debe actualizar la propiedad "DeploymentContributors" para especificar su ID de colaborador. Este es el mismo identificador que se usa en el atributo "ExportDeploymentPlanExecutor" del archivo de origen de colaborador. Sin esto, el componente no se ejecuta al construir el proyecto. La propiedad "ContributorArguments" solo debe actualizarse si tiene argumentos necesarios para que el colaborador pueda ejecutarse.

Implementación del proyecto de base de datos

El proyecto se puede publicar o implementar como normal en Visual Studio. Abra una solución que contenga su proyecto SQL y elija la opción "Publicar..." en el menú contextual al hacer clic con el botón derecho en el proyecto, o use F5 para un despliegue de depuración en LocalDB. En este ejemplo se usa "Publicar..." cuadro de diálogo para generar un script de implementación.

Implementación del proyecto de SQL y generación de un informe de implementación

  1. Abra Visual Studio y abra la solución que contiene el proyecto de SQL.

  2. Seleccione el proyecto y presione "F5" para realizar una implementación de depuración. Nota: Dado que el elemento ContributorArguments se establece para que solo se incluya si la configuración es "Depurar", por ahora, el informe de implementación solo se genera para las implementaciones de depuración. Para cambiar esto, quite la instrucción Condition="'$(Configuration)' == 'Debug'" de la definición ContributorArguments.

  3. La salida, como el ejemplo siguiente, debe estar presente en la ventana de salida:

    ------ Deploy started: Project: Database1, Configuration: Debug Any CPU ------
    Finished verifying cached model in 00:00:00
    Deployment reports ->
    
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.summary.xml
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.details.xml
    
      Deployment script generated to:
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyDatabaseProject.sql
    
  4. Abra MyTargetDatabase.summary.xml y examine el contenido. El archivo es similar al ejemplo siguiente 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 idéntico a la base de datos de destino, el informe resultante no es muy significativo. Para obtener resultados más significativos, implemente cambios en una base de datos o implemente una nueva base de datos.

  5. 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 imprimen un mensaje sobre cómo crear una tabla y que crean la tabla:

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

    Al analizar el plan de implementación a medida que se ejecuta, puede informar sobre cualquier información contenida en la implementación y puede realizar más acciones en función de los pasos de ese plan.