Compartir a través de


Tutorial: Extender la implementación del proyecto de base de datos para modificar 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 DeploymentPlanModifier denominado SqlRestartableScriptContributor que agrega instrucciones IF a los lotes del script de implementación a fin de permitir que el script se vuelva a ejecutar hasta que se complete en caso de producirse un error durante la ejecución.

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

  • Crear el tipo DeploymentPlanModifier 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 SqlRestartableScriptContributor que herede de DeploymentPlanModifier

  • Reemplazar el método OnExecute

  • Agregar métodos auxiliares privados

  • Compilar el ensamblado resultante

Para crear un proyecto de biblioteca de clases

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

  2. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto y, a continuación, haga clic en Agregar referencia.

  3. Haga clic en la ficha .NET.

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

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

Para definir la clase SqlRestartableScriptContributor

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

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Data.Schema.Build;
    using Microsoft.Data.Schema.ScriptDom.Sql;
    using Microsoft.Data.Schema.SchemaModel;
    using System.Globalization;
    using Microsoft.Data.Schema.ScriptDom;
    using Microsoft.Data.Schema.Extensibility;
    using Microsoft.Data.Schema.Sql;
    using Microsoft.Data.Schema.Sql.Build;
    using Microsoft.Data.Schema.Sql.SchemaModel;
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports Microsoft.Data.Schema.Build
    Imports Microsoft.Data.Schema.ScriptDom.Sql
    Imports Microsoft.Data.Schema.SchemaModel
    Imports System.Globalization
    Imports Microsoft.Data.Schema.ScriptDom
    Imports Microsoft.Data.Schema.Extensibility
    Imports Microsoft.Data.Schema.Sql
    Imports Microsoft.Data.Schema.Sql.Build
    Imports Microsoft.Data.Schema.Sql.SchemaModel
    
  2. Actualice la definición de clase para que coincida con el siguiente ejemplo:

            /// <summary>
        /// This deployment contributor modifies a deployment plan by adding if statements
        /// to the existing batches in order to make a deployment script able to be rerun to completion
        /// if an error is encountered during execution
        /// </summary>
        [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
        class SqlRestartableScriptContributor : DeploymentPlanModifier
        {
        }
    
    ''' <summary> 
    ''' This deployment contributor modifies a deployment plan by adding if statements 
    ''' to the existing batches in order to make a deployment script able to be rerun to completion 
    ''' if an error is encountered during execution 
    ''' </summary> 
    <DatabaseSchemaProviderCompatibility(GetType(SqlDatabaseSchemaProvider))> _
    Class SqlRestartableScriptContributor
        Inherits DeploymentPlanModifier
    End Class
    

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

  3. Agregue las siguientes declaraciones de miembro:

            private const string BatchIdColumnName = "BatchId";
            private const string DescriptionColumnName = "Description";
    
            private const string CompletedBatchesVariableName = "CompletedBatches";
            private const string CompletedBatchesVariable = "$(CompletedBatches)";
            private const string CompletedBatchesSqlCmd = @":setvar " + CompletedBatchesVariableName + " __completedBatches_{0}_{1}";
            private const string TotalBatchCountSqlCmd = @":setvar TotalBatchCount {0}";
            private const string CreateCompletedBatchesTable = @"
    if OBJECT_ID(N'tempdb.dbo." + CompletedBatchesVariable + @"', N'U') is null
    begin
    use tempdb
    create table [dbo].[$(CompletedBatches)]
    (
    BatchId int primary key,
    Description nvarchar(300)
    )
    use [$(DatabaseName)]
    end
    ";
            private const string DropCompletedBatchesTable = @"drop table [tempdb].[dbo].[" + CompletedBatchesVariable + "]";
    
        Private Const BatchIdColumnName As String = "BatchId"
        Private Const DescriptionColumnName As String = "Description"
    
        Private Const CompletedBatchesVariableName As String = "CompletedBatches"
        Private Const CompletedBatchesVariable As String = "$(CompletedBatches)"
        Private Const CompletedBatchesSqlCmd As String = ":setvar " & CompletedBatchesVariableName & " __completedBatches_{0}_{1}"
        Private Const TotalBatchCountSqlCmd As String = ":setvar TotalBatchCount {0}"
        Private Const CreateCompletedBatchesTable As String = vbCr & vbLf & "if OBJECT_ID(N'tempdb.dbo." & CompletedBatchesVariable & "', N'U') is null" & vbCr & vbLf & "begin" & vbCr & vbLf & vbTab & "use tempdb" & vbTab & vbCr & vbLf & vbTab & "create table [dbo].[$(CompletedBatches)]" & vbCr & vbLf & vbTab & "(" & vbCr & vbLf & vbTab & vbTab & "BatchId int primary key," & vbCr & vbLf & vbTab & vbTab & "Description nvarchar(300)" & vbCr & vbLf & vbTab & ")" & vbCr & vbLf & vbTab & "use [$(DatabaseName)]" & vbTab & vbCr & vbLf & "end" & vbCr & vbLf
        Private Const DropCompletedBatchesTable As String = "drop table [tempdb].[dbo].[" & CompletedBatchesVariable & "]"
    

    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

  1. Agregue el método siguiente a su clase SqlRestartableScriptContributor:

            /// <summary>
            /// You override the OnExecute method to do the real work of the contributor.
            /// </summary>
            /// <param name="context"></param>
            protected override void OnExecute(DeploymentPlanContributorContext context)
            {
                 // Replace this with the method body
            }
    
        ''' <summary> 
        ''' You override the OnExecute method to do the real work of the contributor. 
        ''' </summary> 
        ''' <param name="context"></param> 
        Protected Overloads Overrides Sub OnExecute(ByVal context As DeploymentPlanContributorContext)
            ' Replace this with the method body
        End Sub
    

    Reemplace el método OnExecute de la clase base, DeploymentPlanContributor, que es la clase base para DeploymentPlanModifier y DeploymentPlanExecutor. 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 plan de implementación y el nombre de la base de datos de destino.

  2. Ahora agregue el principio de un cuerpo al método OnExecute:

            // Obtain the first step in the Plan from the provided context
            DeploymentStep nextStep = context.PlanHandle.Head;
            int batchId = 0;
            BeginPreDeploymentScriptStep beforePreDeploy = null;
    
            // Loop through all steps in the deployment plan
            while (nextStep != null)
            {
                // Increment the step pointer, saving both the current and next steps
                DeploymentStep currentStep = nextStep;
                nextStep = currentStep.Next;
    
                // Add additional step processing here
            }
    
            // if we found steps that required processing, set up a temporary table to track the work that you are doing
            if (beforePreDeploy != null)
            {
                // Add additional post-processing here
            }
    
            // Cleanup and drop the table 
            DeploymentScriptStep dropStep = new DeploymentScriptStep(DropCompletedBatchesTable);
            base.AddAfter(context.PlanHandle, context.PlanHandle.Tail, dropStep);
    
            ' Obtain the first step in the Plan from the provided context 
            Dim nextStep As DeploymentStep = context.PlanHandle.Head
            Dim batchId As Integer = 0
            Dim beforePreDeploy As BeginPreDeploymentScriptStep = Nothing
    
            ' Loop through all steps in the deployment plan 
            While nextStep IsNot Nothing
                ' Increment the step pointer, saving both the current and next steps 
                Dim currentStep As DeploymentStep = nextStep
                nextStep = currentStep.[Next]
    
                '  Add additional step processing here
            End While
    
            ' if we found steps that required processing, set up a temporary table to track the work that you are doing 
            If beforePreDeploy IsNot Nothing Then
                '  Add additional post-processing here
            End If
    
            ' Cleanup and drop the table 
            Dim dropStep As New DeploymentScriptStep(DropCompletedBatchesTable)
            MyBase.AddAfter(context.PlanHandle, context.PlanHandle.Tail, dropStep)
    

    En este código, definimos unas cuantas variables locales y configuramos el bucle que controlará el procesamiento de todos los pasos del plan de implementación. Una vez completado el bucle, tendremos que hacer algún procesamiento posterior y, a continuación, colocaremos la tabla temporal que creamos durante la implementación para realizar el seguimiento del progreso a medida que el plan se ejecutaba. Los tipos clave aquí son: DeploymentStep y DeploymentScriptStep. Un método clave es AddAfter.

  3. Ahora agregue el procesamiento de paso adicional para reemplazar el comentario que indica "Add additional step processing here":

                // Look for steps that mark the pre/post deployment scripts
                // These steps will always be in the deployment plan even if the
                // user's project does not have a pre/post deployment script
                if (currentStep is BeginPreDeploymentScriptStep)
                {
                    // This step marks the begining of the predeployment script.
                    // Save the step and move on.
                    beforePreDeploy = (BeginPreDeploymentScriptStep)currentStep;
                    continue;
                }
                if (currentStep is BeginPostDeploymentScriptStep)
                {
                    // This is the step that marks the beginning of the post deployment script.  
                    // We do not continue processing after this point.
                    break;
                }
                if (currentStep is SqlPrintStep)
                {
                    // We do not need to put if statements around these
                    continue;
                }
    
                // if we have not yet found the beginning of the pre-deployment script steps, 
                // skip to the next step.
                if (beforePreDeploy == null)
                {
                    // We only surround the "main" statement block with conditional
                    // statements
                    continue;
                }
    
                // Determine if this is a step that we need to surround with a conditional statement
                DeploymentScriptDomStep domStep = currentStep as DeploymentScriptDomStep ;
                if (domStep == null)
                {
                    // This step is not a step that we know how to modify,
                    // so skip to the next step.
                    continue;
                }
    
                TSqlScript script = domStep.Script as TSqlScript;
                if (script == null)
                {
                    // The script dom step does not have a script with batches - skip
                    continue;
                }
    
                // Loop through all the batches in the script for this step.  All the statements
                // in the batch will be enclosed in an if statement that will check the
                // table to ensure that the batch has not already been executed
                IModelElement element;
                string stepDescription;
                GetStepInfo(context, domStep, out stepDescription, out element);
                int batchCount = script.Batches.Count;
    
                for (int batchIndex = 0; batchIndex < batchCount; batchIndex++)
                {
                    // Add batch processing here
                }
    
                ' Look for steps that mark the pre/post deployment scripts 
                ' These steps will always be in the deployment plan even if the 
                ' user's project does not have a pre/post deployment script 
                If TypeOf currentStep Is BeginPreDeploymentScriptStep Then
                    ' This step marks the begining of the predeployment script. 
                    ' Save the step and move on. 
                    beforePreDeploy = DirectCast(currentStep, BeginPreDeploymentScriptStep)
                    Continue While
                End If
                If TypeOf currentStep Is BeginPostDeploymentScriptStep Then
                    ' This is the step that marks the beginning of the post deployment script. 
                    ' We do not continue processing after this point. 
                    Exit While
                End If
                If TypeOf currentStep Is SqlPrintStep Then
                    ' We do not need to put if statements around these 
                    Continue While
                End If
    
                ' if we have not yet found the beginning of the pre-deployment script steps, 
                ' skip to the next step. 
                If beforePreDeploy Is Nothing Then
                    ' We only surround the "main" statement block with conditional 
                    ' statements 
                    Continue While
                End If
    
                ' Determine if this is a step that we need to surround with a conditional statement 
                Dim domStep As DeploymentScriptDomStep = TryCast(currentStep, DeploymentScriptDomStep)
                If domStep Is Nothing Then
                    ' This step is not a step that we know how to modify, 
                    ' so skip to the next step. 
                    Continue While
                End If
    
                Dim script As TSqlScript = TryCast(domStep.Script, TSqlScript)
                If script Is Nothing Then
                    ' The script dom step does not have a script with batches - skip 
                    Continue While
                End If
    
                ' Loop through all the batches in the script for this step. All the statements 
                ' in the batch will be enclosed in an if statement that will check the 
                ' table to ensure that the batch has not already been executed 
                Dim element As IModelElement = Nothing
                Dim stepDescription As String = ""
                GetStepInfo(context, domStep, stepDescription, element)
                Dim batchCount As Integer = script.Batches.Count
    
                For batchIndex As Integer = 0 To batchCount - 1
                    ' Add batch processing here
                Next
    

    Los comentarios de código explican el procesamiento. A alto nivel, este código busca los pasos que le importan, mientras omite otros y se detiene cuando alcanza el principio de los pasos de implementación posterior. Si el paso contiene instrucciones que debemos rodear con condicionales, realizaremos procesamiento adicional. Los tipos, métodos y propiedades clave incluyen: BeginPreDeploymentScriptStep, BeginPostDeploymentScriptStep, IModelElement, TSqlScript, Script, DeploymentScriptDomStep y SqlPrintStep.

  4. Ahora, agregue el código de procesamiento por lotes reemplazando el comentario que indica "Add batch processing here":

                        // Create the if statement that will contain the batch's contents
                        IfStatement ifBatchNotExecutedStatement = CreateIfNotExecutedStatement(batchId);
                        BeginEndBlockStatement statementBlock = new BeginEndBlockStatement();
                        ifBatchNotExecutedStatement.ThenStatement = statementBlock;
                        statementBlock.StatementList = new StatementList();
    
                        TSqlBatch batch = script.Batches[batchIndex];
                        int statementCount = batch.Statements.Count;
    
                        // Loop through all statements in the batch, embedding those in an sp_execsql
                        // statement that must be handled this way (schemas, stored procedures, 
                        // views, functions, and triggers).
                        for (int statementIndex = 0; statementIndex < statementCount; statementIndex++)
                        {
                            // Add additional statement processing here
                        }
    
                        // Add an insert statement to track that all the statements in this
                        // batch were executed.  Turn on nocount to improve performance by
                        // avoiding row inserted messages from the server
                        string batchDescription = string.Format(CultureInfo.InvariantCulture,
                            "{0} batch {1}", stepDescription, batchIndex);
    
                        PredicateSetStatement noCountOff = new PredicateSetStatement();
                        noCountOff.IsOn = false;
                        noCountOff.Options = SetOptions.NoCount;
    
                        PredicateSetStatement noCountOn = new PredicateSetStatement();
                        noCountOn.IsOn = true;
                        noCountOn.Options = SetOptions.NoCount; 
                        InsertStatement batchCompleteInsert = CreateBatchCompleteInsert(batchId, batchDescription);
                        statementBlock.StatementList.Statements.Add(noCountOn);
                        statementBlock.StatementList.Statements.Add(batchCompleteInsert);
                        statementBlock.StatementList.Statements.Add(noCountOff);
    
                        // Remove all the statements from the batch (they are now in the if block) and add the if statement
                        // as the sole statement in the batch
                        batch.Statements.Clear();
                        batch.Statements.Add(ifBatchNotExecutedStatement);
    
                        // Next batch
                        batchId++;
    
                    ' Create the if statement that will contain the batch's contents 
                    Dim ifBatchNotExecutedStatement As IfStatement = CreateIfNotExecutedStatement(batchId)
                    Dim statementBlock As New BeginEndBlockStatement()
                    ifBatchNotExecutedStatement.ThenStatement = statementBlock
                    statementBlock.StatementList = New StatementList()
    
                    Dim batch As TSqlBatch = script.Batches(batchIndex)
                    Dim statementCount As Integer = batch.Statements.Count
    
                    ' Loop through all statements in the batch, embedding those in an sp_execsql 
                    ' statement that must be handled this way (schemas, stored procedures, 
                    ' views, functions, and triggers). 
                    For statementIndex As Integer = 0 To statementCount - 1
                        ' Add additional statement processing here
                    Next
    
                    ' Add an insert statement to track that all the statements in this 
                    ' batch were executed. Turn on nocount to improve performance by 
                    ' avoiding row inserted messages from the server 
                    Dim batchDescription As String = String.Format(CultureInfo.InvariantCulture, "{0} batch {1}", stepDescription, batchIndex)
    
                    Dim noCountOff As New PredicateSetStatement()
                    noCountOff.IsOn = False
                    noCountOff.Options = SetOptions.NoCount
    
                    Dim noCountOn As New PredicateSetStatement()
                    noCountOn.IsOn = True
                    noCountOn.Options = SetOptions.NoCount
                    Dim batchCompleteInsert As InsertStatement = CreateBatchCompleteInsert(batchId, batchDescription)
                    statementBlock.StatementList.Statements.Add(noCountOn)
                    statementBlock.StatementList.Statements.Add(batchCompleteInsert)
                    statementBlock.StatementList.Statements.Add(noCountOff)
    
                    ' Remove all the statements from the batch (they are now in the if block) and add the if statement 
                    ' as the sole statement in the batch 
                    batch.Statements.Clear()
                    batch.Statements.Add(ifBatchNotExecutedStatement)
    
                    ' Next batch 
                    batchId += 1
    

    Este código crea una instrucción IF junto con un bloque BEGIN/END. A continuación, realizamos procesamiento adicional en las instrucciones del lote. Una vez completado, agregamos una instrucción INSERT para agregar información a la tabla temporal que realiza el seguimiento del progreso de la ejecución del script. Por último, actualizaremos el lote, reemplazando las instrucciones que solían estar allí por la nueva instrucción IF que contiene esas instrucciones en su interior.

    Los tipos, métodos y propiedades clave incluyen: IfStatement, BeginEndBlockStatement, StatementList, TSqlBatch, PredicateSetStatement, SetOptions e InsertStatement.

  5. Ahora, agregue el cuerpo del bucle de procesamiento de instrucciones. Reemplace el comentario que indica "Add additional statement processing here":

                            TSqlStatement smnt = batch.Statements[statementIndex];
    
                            if (IsStatementEscaped(element))
                            {
                                // "escape" this statement by embedding it in a sp_executesql statement
                                string statementScript = null;
                                domStep.ScriptGenerator.GenerateScript(smnt, out statementScript);
                                ExecuteStatement spExecuteSql = CreateExecuteSql(statementScript);
                                smnt = spExecuteSql;
                            }
    
                            statementBlock.StatementList.Statements.Add(smnt);
    
                        Dim smnt As TSqlStatement = batch.Statements(statementIndex)
    
                        If IsStatementEscaped(element) Then
                            ' "escape" this statement by embedding it in a sp_executesql statement 
                            Dim statementScript As String = Nothing
                            domStep.ScriptGenerator.GenerateScript(smnt, statementScript)
                            Dim spExecuteSql As ExecuteStatement = CreateExecuteSql(statementScript)
                            smnt = spExecuteSql
                        End If
    
                        statementBlock.StatementList.Statements.Add(smnt)
    

    En cada instrucción del lote, si ésta es de un tipo que se debe ajustar con una instrucción sp_executesql, modifique la instrucción en consecuencia. Entonces, el código agrega la instrucción a la lista de instrucciones del bloque BEGIN/END que creó. Los tipos, métodos y propiedades clave incluyen TSqlStatement y ExecuteStatement.

  6. Finalmente, agregue la sección de procesamiento posterior en lugar del comentario que indica "Add additional post-processing here":

                    // Declare a SqlCmd variables.
                    //
                    // CompletedBatches variable - defines the name of the table in tempdb that will track
                    // all the completed batches.  The temporary table's name has the target database name and
                    // a guid embedded in it so that:
                    // * Multiple deployment scripts targeting different DBs on the same server
                    // * Failed deployments with old tables do not conflict with more recent deployments
                    //
                    // TotalBatchCount variable - the total number of batches surrounded by if statements.  Using this
                    // variable pre/post deployment scripts can also use the CompletedBatches table to make their
                    // script rerunnable if there is an error during execution
                    StringBuilder sqlcmdVars = new StringBuilder();
                    sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, CompletedBatchesSqlCmd,
                        context.Options.TargetDatabaseName, Guid.NewGuid().ToString("D"));
                    sqlcmdVars.AppendLine();
                    sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, TotalBatchCountSqlCmd, batchId);
    
                    DeploymentScriptStep completedBatchesSetVarStep = new DeploymentScriptStep(sqlcmdVars.ToString());
                    base.AddBefore(context.PlanHandle, beforePreDeploy, completedBatchesSetVarStep);
    
                    // Create the temporary table we will use to track the work that we are doing
                    DeploymentScriptStep createStatusTableStep = new DeploymentScriptStep(CreateCompletedBatchesTable);
                    base.AddBefore(context.PlanHandle, beforePreDeploy, createStatusTableStep);
    
                ' Declare a SqlCmd variables. 
                ' 
                ' CompletedBatches variable - defines the name of the table in tempdb that will track 
                ' all the completed batches. The temporary table's name has the target database name and 
                ' a guid embedded in it so that: 
                ' * Multiple deployment scripts targeting different DBs on the same server 
                ' * Failed deployments with old tables do not conflict with more recent deployments 
                ' 
                ' TotalBatchCount variable - the total number of batches surrounded by if statements. Using this 
                ' variable pre/post deployment scripts can also use the CompletedBatches table to make their 
                ' script rerunnable if there is an error during execution 
                Dim sqlcmdVars As New StringBuilder()
                sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, CompletedBatchesSqlCmd, context.Options.TargetDatabaseName, Guid.NewGuid().ToString("D"))
                sqlcmdVars.AppendLine()
                sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, TotalBatchCountSqlCmd, batchId)
    
                Dim completedBatchesSetVarStep As New DeploymentScriptStep(sqlcmdVars.ToString())
                MyBase.AddBefore(context.PlanHandle, beforePreDeploy, completedBatchesSetVarStep)
    
                ' Create the temporary table we will use to track the work that we are doing 
                Dim createStatusTableStep As New DeploymentScriptStep(CreateCompletedBatchesTable)
                MyBase.AddBefore(context.PlanHandle, beforePreDeploy, createStatusTableStep)
    

    Si nuestro procesamiento detectó uno o más pasos rodeados con una instrucción condicional, debemos agregar instrucciones al script de implementación para definir variables SQLCMD. La primera variable, CompletedBatches, contiene un nombre único para la tabla temporal que el script de implementación utiliza para realizar el seguimiento de los lotes que se completaron correctamente cuando se ejecutó el script. La segunda variable, TotalBatchCount, contiene el número total de lotes del script de implementación.

    Los tipos, propiedades y métodos de interés adicionales incluyen:

    StringBuilder, DeploymentScriptStep y AddBefore.

    A continuación, defina los métodos auxiliares llamados por este método.

Para agregar el método CreateExecuteSql

  • Agregue el siguiente código para definir el método CreateExecuteSQL para rodear una instrucción proporcionada con una instrucción EXEC sp_executesql:

            /// <summary>
            /// The CreateExecuteSql method "wraps" the provided statement script in an "sp_executesql" statement
            /// Examples of statements that must be so wrapped include: stored procedures, views, and functions
            /// </summary>
            /// <param name="string"></param>
            /// <returns></returns>
            private static ExecuteStatement CreateExecuteSql(string statementScript)
            {
                // define a new Exec statement
                ExecuteStatement executeSp = new ExecuteStatement();
                ExecutableProcedureReference spExecute = new ExecutableProcedureReference();
                executeSp.ExecutableEntity = spExecute;
    
                // define the name of the procedure that you want to execute, in this case sp_executesql
                SchemaObjectName procName = new SchemaObjectName();
                procName.Identifiers.Add(CreateIdentifier("sp_executesql", QuoteType.NotQuoted));
                ProcedureReference procRef = new ProcedureReference();
                procRef.Name = procName;
                spExecute.ProcedureReference = procRef;
    
                // add the script parameter, constructed from the provided statement script
                ExecuteParameter scriptParam = new ExecuteParameter();
                spExecute.Parameters.Add(scriptParam);
                scriptParam.ParameterValue = CreateLiteral(statementScript, LiteralType.UnicodeStringLiteral);
                scriptParam.Variable = CreateLiteral("@stmt", LiteralType.Variable);
                return executeSp;
            }
    
        ''' <summary> 
        ''' The CreateExecuteSql method "wraps" the provided statement script in an "sp_executesql" statement 
        ''' Examples of statements that must be so wrapped include: stored procedures, views, and functions 
        ''' </summary> 
        ''' <param name="statementScript"></param> 
        ''' <returns></returns> 
        Private Shared Function CreateExecuteSql(ByVal statementScript As String) As ExecuteStatement
            ' define a new Exec statement 
            Dim executeSp As New ExecuteStatement()
            Dim spExecute As New ExecutableProcedureReference()
            executeSp.ExecutableEntity = spExecute
    
            ' define the name of the procedure that you want to execute, in this case sp_executesql 
            Dim procName As New SchemaObjectName()
            procName.Identifiers.Add(CreateIdentifier("sp_executesql", QuoteType.NotQuoted))
            Dim procRef As New ProcedureReference()
            procRef.Name = procName
            spExecute.ProcedureReference = procRef
    
            ' add the script parameter, constructed from the provided statement script 
            Dim scriptParam As New ExecuteParameter()
            spExecute.Parameters.Add(scriptParam)
            scriptParam.ParameterValue = CreateLiteral(statementScript, LiteralType.UnicodeStringLiteral)
            scriptParam.Variable = CreateLiteral("@stmt", LiteralType.Variable)
            Return executeSp
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: ExecuteStatement, ExecutableProcedureReference, SchemaObjectName, ProcedureReference y ExecuteParameter.

Para agregar el método CreateLiteral

  • Agregue el código siguiente para definir el método CreateLiteral. Este método crea un objeto Literal del tipo especificado a partir de la cadena proporcionada:

            /// <summary>
            /// The CreateLiteral method creates a Literal object of the specified type from the provided string
            /// </summary>
            /// <param name="value"></param>
            /// <param name="type"></param>
            /// <returns></returns>
            private static Literal CreateLiteral(string value, LiteralType type)
            {
                Literal l = new Literal();
                l.Value = value;
                l.LiteralType = type;
                return l;
            }
    
        ''' <summary> 
        ''' The CreateLiteral method creates a Literal object of the specified type from the provided string 
        ''' </summary> 
        ''' <param name="value"></param> 
        ''' <param name="type"></param> 
        ''' <returns></returns> 
        Private Shared Function CreateLiteral(ByVal value As String, ByVal type As LiteralType) As Literal
            Dim l As New Literal()
            l.Value = value
            l.LiteralType = type
            Return l
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: Literal y LiteralType.

Para agregar el método CreateIdentifier

  • Agregue el código siguiente para definir el método CreateIdentifier. Este método crea un objeto Identifier que utiliza el tipo especificado de entrecomillado de la cadena proporcionada:

            /// <summary>
            /// The CreateIdentifier method returns a Identifier with the specified value and quoting type
            /// </summary>
            /// <param name="value"></param>
            /// <param name="quoteType"></param>
            /// <returns></returns>
            private static Identifier CreateIdentifier(string value, QuoteType quoteType)
            {
                Identifier id = new Identifier();
                id.Value = value;
                id.QuoteType = quoteType;
                return id;
            }
    
        ''' <summary> 
        ''' The CreateIdentifier method returns a Identifier with the specified value and quoting type 
        ''' </summary> 
        ''' <param name="value"></param> 
        ''' <param name="quoteType"></param> 
        ''' <returns></returns> 
        Private Shared Function CreateIdentifier(ByVal value As String, ByVal quoteType As QuoteType) As Identifier
            Dim id As New Identifier()
            id.Value = value
            id.QuoteType = quoteType
            Return id
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: Identifier y QuoteType.

Para agregar el método CreateCompletedBatchesName

  • Agregue el código siguiente para definir el método CreateCompletedBatchesName. Este método crea el nombre que se insertará en la tabla temporal de un lote:

            /// <summary>
            /// The CreateCompletedBatchesName method creates the name that will be inserted
            /// into the temporary table for a batch.
            /// </summary>
            /// <returns></returns>
            private static SchemaObjectName CreateCompletedBatchesName()
            {
                SchemaObjectName name = new SchemaObjectName();
                name.Identifiers.Add(CreateIdentifier("tempdb", QuoteType.SquareBracket));
                name.Identifiers.Add(CreateIdentifier("dbo", QuoteType.SquareBracket));
                name.Identifiers.Add(CreateIdentifier(CompletedBatchesVariable, QuoteType.SquareBracket));
                return name;
            }
    
        ''' <summary> 
        ''' The CreateCompletedBatchesName method creates the name that will be inserted 
        ''' into the temporary table for a batch. 
        ''' </summary> 
        ''' <returns></returns> 
        Private Shared Function CreateCompletedBatchesName() As SchemaObjectName
            Dim name As New SchemaObjectName()
            name.Identifiers.Add(CreateIdentifier("tempdb", QuoteType.SquareBracket))
            name.Identifiers.Add(CreateIdentifier("dbo", QuoteType.SquareBracket))
            name.Identifiers.Add(CreateIdentifier(CompletedBatchesVariable, QuoteType.SquareBracket))
            Return name
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: SchemaObjectName.

Para agregar el método IsStatementEscaped

  • Agregue el código siguiente para definir el método IsStatementEscaped. Este método determina si el tipo de elemento modelo exige ajustar la instrucción con una instrucción EXEC sp_executesql antes de poder incluirla en una instrucción IF:

            /// <summary>
            /// Helper method that determins whether the specified statement needs to
            /// be escaped
            /// </summary>
            /// <param name="smnt"></param>
            /// <returns></returns>
            private static bool IsStatementEscaped(IModelElement element)
            {
                return element is ISql90Schema
                    || element is ISqlProcedure
                    || element is ISqlView
                    || element is ISqlFunction
                    || element is ISqlTrigger;
            }
    
        ''' <summary> 
        ''' Helper method that determins whether the specified statement needs to 
        ''' be escaped 
        ''' </summary> 
        ''' <param name="element"></param> 
        ''' <returns></returns> 
        Private Shared Function IsStatementEscaped(ByVal element As IModelElement) As Boolean
            Return TypeOf element Is ISql90Schema OrElse TypeOf element Is ISqlProcedure OrElse TypeOf element Is ISqlView OrElse TypeOf element Is ISqlFunction OrElse TypeOf element Is ISqlTrigger
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: IModelElement, ISql90Schema, ISqlProcedure, ISqlView, ISqlFunction e ISqlTrigger.

Para agregar el método CreateBatchCompleteInsert

  • Agregue el código siguiente para definir el método CreateBatchCompleteInsert. Este método crea la instrucción INSERT que se agregará al script de implementación para realizar el seguimiento del progreso de la ejecución del script:

            /// <summary>
            /// Helper method that creates an INSERT statement to track a batch being completed
            /// </summary>
            /// <param name="batchId"></param>
            /// <param name="batchDescription"></param>
            /// <returns></returns>
            private static InsertStatement CreateBatchCompleteInsert(int batchId, string batchDescription)
            {
                InsertStatement insert = new InsertStatement();
                SchemaObjectDataModificationTarget batchesCompleted = new SchemaObjectDataModificationTarget();
                insert.Target = batchesCompleted;
                batchesCompleted.SchemaObject = CreateCompletedBatchesName();
    
                // Build the columns inserted into
                Column batchIdColumn = new Column();
                batchIdColumn.Identifiers.Add(CreateIdentifier(BatchIdColumnName, QuoteType.NotQuoted));
    
                Column descriptionColumn = new Column();
                descriptionColumn.Identifiers.Add(CreateIdentifier(DescriptionColumnName, QuoteType.NotQuoted));
    
                insert.Columns.Add(batchIdColumn);
                insert.Columns.Add(descriptionColumn);
    
                // Build the values inserted
                ValuesInsertSource valueSource = new ValuesInsertSource();
                insert.InsertSource = valueSource;
    
                RowValue values = new RowValue();
                values.ColumnValues.Add(CreateLiteral(batchId.ToString(), LiteralType.Integer));
                values.ColumnValues.Add(CreateLiteral(batchDescription, LiteralType.UnicodeStringLiteral));
                valueSource.RowValues.Add(values);
    
                return insert;
            }
    
        ''' <summary> 
        ''' Helper method that creates an INSERT statement to track a batch being completed 
        ''' </summary> 
        ''' <param name="batchId"></param> 
        ''' <param name="batchDescription"></param> 
        ''' <returns></returns> 
        Private Shared Function CreateBatchCompleteInsert(ByVal batchId As Integer, ByVal batchDescription As String) As InsertStatement
            Dim insert As New InsertStatement()
            Dim batchesCompleted As New SchemaObjectDataModificationTarget()
            insert.Target = batchesCompleted
            batchesCompleted.SchemaObject = CreateCompletedBatchesName()
    
            ' Build the columns inserted into 
            Dim batchIdColumn As New Column()
            batchIdColumn.Identifiers.Add(CreateIdentifier(BatchIdColumnName, QuoteType.NotQuoted))
    
            Dim descriptionColumn As New Column()
            descriptionColumn.Identifiers.Add(CreateIdentifier(DescriptionColumnName, QuoteType.NotQuoted))
    
            insert.Columns.Add(batchIdColumn)
            insert.Columns.Add(descriptionColumn)
    
            ' Build the values inserted 
            Dim valueSource As New ValuesInsertSource()
            insert.InsertSource = valueSource
    
            Dim values As New RowValue()
            values.ColumnValues.Add(CreateLiteral(batchId.ToString(), LiteralType.[Integer]))
            values.ColumnValues.Add(CreateLiteral(batchDescription, LiteralType.UnicodeStringLiteral))
            valueSource.RowValues.Add(values)
    
            Return insert
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: InsertStatement, SchemaObjectDataModificationTarget, Column, ValuesInsertSource y RowValue.

Para agregar el método CreateIfNotExecutedStatement

  • Agregue el código siguiente para definir el método CreateIfNotExecutedStatement. Este método genera una instrucción IF que comprueba si la tabla de ejecución de lotes temporales indica que ya se ha ejecutado este lote:

            /// <summary>
            /// This is a helper method that generates an if statement that checks the batches executed
            /// table to see if the current batch has been executed.  The if statement will look like this
            /// 
            /// if not exists(select 1 from [tempdb].[dbo].[$(CompletedBatches)] 
            ///                where BatchId = batchId)
            /// begin
            /// end
            /// </summary>
            /// <param name="batchId"></param>
            /// <returns></returns>
            private static IfStatement CreateIfNotExecutedStatement(int batchId)
            {
                // Create the exists/select statement
                ExistsPredicate existsExp = new ExistsPredicate();
                Subquery subQuery = new Subquery();
                existsExp.Subquery = subQuery;
    
                QuerySpecification select = new QuerySpecification();
                subQuery.QueryExpression = select;
                select.SelectElements.Add(CreateLiteral("1", LiteralType.Integer));
                SchemaObjectTableSource completedBatchesTable = new SchemaObjectTableSource();
                select.FromClauses.Add(completedBatchesTable);
                completedBatchesTable.SchemaObject = CreateCompletedBatchesName();
    
                WhereClause where = new WhereClause();
                select.WhereClause = where;
    
                Column batchIdColumn = new Column();
                batchIdColumn.Identifiers.Add(CreateIdentifier(BatchIdColumnName, QuoteType.SquareBracket));
                Literal batchIdValue = CreateLiteral(batchId.ToString(), LiteralType.Integer);
    
                BinaryExpression stepsEqual = new BinaryExpression();
                where.SearchCondition = stepsEqual;
                stepsEqual.BinaryExpressionType = BinaryExpressionType.Equals;
                stepsEqual.FirstExpression = batchIdColumn;
                stepsEqual.SecondExpression = batchIdValue;
    
                // Put together the rest of the statement
                IfStatement ifNotExists = new IfStatement();
                UnaryExpression notExp = new UnaryExpression();
                ifNotExists.Predicate = notExp;
                notExp.UnaryExpressionType = UnaryExpressionType.Not;
                notExp.Expression = existsExp;
    
                return ifNotExists;
            }
    
        ''' <summary> 
        ''' This is a helper method that generates an if statement that checks the batches executed 
        ''' table to see if the current batch has been executed. The if statement will look like this 
        ''' 
        ''' if not exists(select 1 from [tempdb].[dbo].[$(CompletedBatches)] 
        ''' where BatchId = batchId) 
        ''' begin 
        ''' end 
        ''' </summary> 
        ''' <param name="batchId"></param> 
        ''' <returns></returns> 
        Private Shared Function CreateIfNotExecutedStatement(ByVal batchId As Integer) As IfStatement
            ' Create the exists/select statement 
            Dim existsExp As New ExistsPredicate()
            Dim subQuery As New Subquery()
            existsExp.Subquery = subQuery
    
            Dim [select] As New QuerySpecification()
            subQuery.QueryExpression = [select]
            [select].SelectElements.Add(CreateLiteral("1", LiteralType.[Integer]))
            Dim completedBatchesTable As New SchemaObjectTableSource()
            [select].FromClauses.Add(completedBatchesTable)
            completedBatchesTable.SchemaObject = CreateCompletedBatchesName()
    
            Dim where As New WhereClause()
            [select].WhereClause = where
    
            Dim batchIdColumn As New Column()
            batchIdColumn.Identifiers.Add(CreateIdentifier(BatchIdColumnName, QuoteType.SquareBracket))
            Dim batchIdValue As Literal = CreateLiteral(batchId.ToString(), LiteralType.[Integer])
    
            Dim stepsEqual As New BinaryExpression()
            where.SearchCondition = stepsEqual
            stepsEqual.BinaryExpressionType = BinaryExpressionType.Equals
            stepsEqual.FirstExpression = batchIdColumn
            stepsEqual.SecondExpression = batchIdValue
    
            ' Put together the rest of the statement 
            Dim ifNotExists As New IfStatement()
            Dim notExp As New UnaryExpression()
            ifNotExists.Predicate = notExp
            notExp.UnaryExpressionType = UnaryExpressionType.[Not]
            notExp.Expression = existsExp
    
            Return ifNotExists
        End Function
    

    Los tipos, métodos y propiedades clave incluyen: IfStatement, ExistsPredicate, Subquery, SchemaObjectTableSource, WhereClause, Column, Literal, BinaryExpression y UnaryExpression

Para agregar el método GetStepInfo

  1. Agregue el código siguiente para definir el método GetStepInfo. Este método:

            /// <summary>
            /// Helper method that generates a useful description of the step.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="domStep"></param>
            /// <param name="stepDescription"></param>
            /// <param name="element"></param>
            private static void GetStepInfo(
                DeploymentPlanContributorContext context, 
                DeploymentScriptDomStep domStep,
                out string stepDescription,
                out IModelElement element)
            {
                element = null;
                CreateElementStep createStep = null;
                AlterElementStep alterStep = null;
                DropElementStep dropStep = null;
    
                // figure out what type of step we've got, and retrieve
                // either the source or target element.
                if ((createStep = domStep as CreateElementStep) != null)
                {
                    element = createStep.SourceElement;
                }
                else if ((alterStep = domStep as AlterElementStep) != null)
                {
                    element = alterStep.SourceElement;
                }
                else if ((dropStep = domStep as DropElementStep) != null)
                {
                    element = dropStep.TargetElement;
                }
    
                // construct the step description by concatenating the type and the fully qualified
                // name of the associated element.
                string stepTypeName = domStep.GetType().Name;
                if (element != null)
                {
                    string elementName = context.Source.DatabaseSchemaProvider.UserInteractionServices.GetElementName(
                        element, Microsoft.Data.Schema.ElementNameStyle.FullyQualifiedName);
    
                    stepDescription = string.Format(CultureInfo.InvariantCulture, "{0} {1}",
                        stepTypeName, elementName);
                }
                else
                {
                    // if the step has no associated element, just use the step type as the description
                    stepDescription = stepTypeName;
                }
            }
    
        ''' <summary> 
        ''' Helper method that generates a useful description of the step. 
        ''' </summary> 
        ''' <param name="context"></param> 
        ''' <param name="domStep"></param> 
        ''' <param name="stepDescription"></param> 
        ''' <param name="element"></param> 
        Private Shared Sub GetStepInfo(ByVal context As DeploymentPlanContributorContext, ByVal domStep As DeploymentScriptDomStep, ByRef stepDescription As String, ByRef element As IModelElement)
            element = Nothing
            Dim createStep As CreateElementStep = Nothing
            Dim alterStep As AlterElementStep = Nothing
            Dim dropStep As DropElementStep = Nothing
    
            ' figure out what type of step we've got, and retrieve 
            ' either the source or target element. 
            If (InlineAssignHelper(createStep, TryCast(domStep, CreateElementStep))) IsNot Nothing Then
                element = createStep.SourceElement
            ElseIf (InlineAssignHelper(alterStep, TryCast(domStep, AlterElementStep))) IsNot Nothing Then
                element = alterStep.SourceElement
            ElseIf (InlineAssignHelper(dropStep, TryCast(domStep, DropElementStep))) IsNot Nothing Then
                element = dropStep.TargetElement
            End If
    
            ' construct the step description by concatenating the type and the fully qualified 
            ' name of the associated element. 
            Dim stepTypeName As String = domStep.[GetType]().Name
            If element IsNot Nothing Then
                Dim elementName As String = context.Source.DatabaseSchemaProvider.UserInteractionServices.GetElementName(element, Microsoft.Data.Schema.ElementNameStyle.FullyQualifiedName)
    
                stepDescription = String.Format(CultureInfo.InvariantCulture, "{0} {1}", stepTypeName, elementName)
            Else
                ' if the step has no associated element, just use the step type as the description 
                stepDescription = stepTypeName
            End If
        End Sub
        Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
            target = value
            Return value
        End Function
    

    Los tipos y métodos de interés incluyen: DeploymentPlanContributorContext, DeploymentScriptDomStep, IModelElement, CreateElementStep, AlterElementStep y DropElementStep.

  2. Guarde los cambios en Class1.cs.

    A continuación, compile la biblioteca de clases.

Para firmar y compilar el ensamblado

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

  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 MyOtherDeploymentContributor

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

  2. Copie el ensamblado firmado (MyOtherDeploymentContributor.dll) en la carpeta %Archivos de programa%\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.

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

Para registrar el ensamblado MyOtherDeploymentContributor

  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:

    "GeneratorAssembly, 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="MyOtherDeploymentContributor.SqlRestartableScriptContributor" 
    assembly="MyOtherDeploymentContributor, 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 MyOtherDeploymentContributor.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 la siguiente tarea:

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

Dado que este colaborador de implementación siempre está habilitado, no tiene que modificar el proyecto de base de datos para agregar cualquier propiedad.

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:Deploy MyDatabaseProject.dbproj
    

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

  4. Examine el script de implementación resultante. Justo antes de la sección etiquetada "Pre-Deployment Script Template", debería ver algo parecido al siguiente Transact-SQL:

    :setvar CompletedBatches __completedBatches_CompareProjectDB_cd1e348a-8f92-44e0-9a96-d25d65900fca
    :setvar TotalBatchCount 17
    GO
    
    if OBJECT_ID(N'tempdb.dbo.$(CompletedBatches)', N'U') is null
    begin
    use tempdb
    create table [dbo].[$(CompletedBatches)]
    (
    BatchId int primary key,
    Description nvarchar(300)
    )
    use [$(DatabaseName)]
    end
    

    Más adelante en el script de implementación, alrededor de cada lote, verá una instrucción IF que rodea a la instrucción original. Por ejemplo, podría aparecer lo siguiente en una instrucción CREATE SCHEMA:

    IF NOT EXISTS (SELECT 1
                   FROM   [tempdb].[dbo].[$(CompletedBatches)]
                   WHERE  [BatchId] = 0)
        BEGIN
            EXECUTE sp_executesql @stmt = N'CREATE SCHEMA [Sales]
        AUTHORIZATION [dbo]';
            SET NOCOUNT ON;
            INSERT  [tempdb].[dbo].[$(CompletedBatches)] (BatchId, Description)
            VALUES                                      (0, N'CreateElementStep Sales batch 0');
            SET NOCOUNT OFF;
        END
    

    Tenga en cuenta que CREATE SCHEMA es una de las instrucciones que deben incluirse en una instrucción EXECUTE sp_executesql dentro de la instrucción IF. Instrucciones como CREATE TABLE no necesitan la instrucción EXECUTE sp_executesql y se parecerán al siguiente ejemplo:

    IF NOT EXISTS (SELECT 1
                   FROM   [tempdb].[dbo].[$(CompletedBatches)]
                   WHERE  [BatchId] = 1)
        BEGIN
            CREATE TABLE [Sales].[Customer] (
                [CustomerID]   INT           IDENTITY (1, 1) NOT NULL,
                [CustomerName] NVARCHAR (40) NOT NULL,
                [YTDOrders]    INT           NOT NULL,
                [YTDSales]     INT           NOT NULL
            );
            SET NOCOUNT ON;
            INSERT  [tempdb].[dbo].[$(CompletedBatches)] (BatchId, Description)
            VALUES                                      (1, N'CreateElementStep Sales.Customer batch 0');
            SET NOCOUNT OFF;
        END
    

    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.

    Puede agregar, quitar o modificar lotes o instrucciones en cualquier plan de implementación mediante un DeploymentPlanModifier.

Pasos siguientes

Puede experimentar con otros tipos de modificaciones que puede realizar a los planes de implementación antes de que se ejecuten. Algunos otros tipos de modificaciones que quizás desee realizar incluyen los siguientes: agregar una propiedad extendida a todos los objetos de base de datos que se asocian un número de versión a sí mismos, agregar o quitar instrucciones de impresión de diagnóstico adicionales o comentarios de scripts de implementación, etc.

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 analizar el plan de implementación