Partager via


Procédure pas à pas : étendre un déploiement de projet de base de données pour analyser le plan de déploiement

Vous pouvez créer des collaborateurs du déploiement pour exécuter des actions personnalisées lorsque vous déployez un projet de base de données. Vous pouvez créer un DeploymentPlanModifier ou un DeploymentPlanExecutor. Utilisez un DeploymentPlanModifier pour modifier le plan avant qu'il ne soit exécuté et un DeploymentPlanExecutor pour réaliser des opérations pendant que le plan est exécuté. Dans cette procédure pas à pas, créez un DeploymentPlanExecutor nommé DeploymentUpdateReportContributor qui crée un rapport concernant les actions exécutées lorsque vous déployez un projet de base de données. Étant donné que ce collaborateur de génération accepte un paramètre pour contrôler si le rapport est généré, vous devez exécuter une étape requise supplémentaire.

Dans cette procédure pas à pas, vous effectuerez les principales tâches suivantes :

  • Créer le type DeploymentPlanExecutor de collaborateur du déploiement

  • Installer le collaborateur du déploiement

  • Tester votre collaborateur du déploiement

Composants requis

Pour exécuter cette procédure pas à pas, vous devez disposer des composants suivants :

  • Visual Studio 2010 Premium ou Visual Studio 2010 Ultimate installé sur votre ordinateur.

  • Projet de base de données qui contient des objets de base de données

  • Instance de SQL Server sur laquelle vous pouvez déployer un projet de base de données

Notes

Cette procédure pas à pas est destinée aux utilisateurs qui sont déjà familiarisés avec les fonctionnalités de base de données de Visual Studio. Vous êtes également censé connaître les concepts Visual Studio de base, tels que les modes de création d'une bibliothèque de classes et d'utilisation de l'éditeur de code pour ajouter du code à une classe.

Créer un collaborateur de déploiement

Pour créer un collaborateur du déploiement, vous devez effectuer les tâches suivantes :

  • Créer un projet de bibliothèque de classes et ajouter les références requises

  • Définir une classe nommée DeploymentUpdateReportContributor qui hérite de DeploymentPlanExecutor

  • Substituer les méthodes OnPopulateArguments et OnExecute.

  • Ajouter une classe d'assistance privée

  • Générer l'assembly obtenu

Pour créer un projet de bibliothèque de classes

  1. Créez un projet de bibliothèque de classes Visual Basic ou Visual C# nommé MyDeploymentContributor.

  2. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le dossier Références, puis cliquez sur Ajouter une référence.

  3. Cliquez sur l'onglet .NET.

  4. Mettez en surbrillance les entrées Microsoft.Data.Schema et Microsoft.Data.Schema.Sql, puis cliquez sur OK.

    Commencez ensuite à ajouter du code à la classe.

Pour définir la classe DeploymentUpdateReportContributor

  1. Dans l'éditeur de code, mettez à jour le fichier class1.cs pour qu'il inclue les instructions using ou Imports suivantes :

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Data.Schema.Build;
    using Microsoft.Data.Schema.Extensibility;
    using Microsoft.Data.Schema.Sql;
    using System.IO;
    using Microsoft.Data.Schema.SchemaModel;
    using System.Xml;
    using Microsoft.Data.Schema;
    using Microsoft.Data.Schema.Sql.Build;
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports Microsoft.Data.Schema.Build
    Imports Microsoft.Data.Schema.Extensibility
    Imports Microsoft.Data.Schema.Sql
    Imports System.IO
    Imports Microsoft.Data.Schema.SchemaModel
    Imports System.Xml
    Imports Microsoft.Data.Schema
    Imports Microsoft.Data.Schema.Sql.Build
    
  2. Mettez à jour la définition de classe comme suit :

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

    À présent, vous avez défini votre collaborateur de génération et utilisé l'attribut pour indiquer que ce collaborateur est compatible avec tous les fournisseurs de schémas de base de données qui héritent de SqlDatabaseSchemaProvider.

  3. Ensuite, ajoutez le membre suivant que vous utiliserez pour permettre à ce fournisseur d'accepter un paramètre de ligne de commande :

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

    Ce membre permet à l'utilisateur de spécifier si le rapport doit être généré à l'aide de l'option GenerateUpdateReport.

    Ensuite, substituez la méthode OnPopulateArguments pour générer la liste d'arguments à passer au collaborateur du déploiement.

Pour substituer OnPopulateArguments

  • Ajoutez la méthode de substitution suivante à la classe DeploymentUpdateReportContributor :

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

    Vous générez un objet ContributorArgumentConfiguration et l'ajoutez à la liste d'arguments. Par défaut, le rapport est généré lorsque vous générez une version debug.

    Substituez ensuite la méthode OnExecute pour ajouter le code que vous souhaitez exécuter lors du déploiement d'un projet de base de données.

Pour substituer OnExecute

  • Ajoutez la méthode suivante à votre classe DeploymentUpdateReportContributor :

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

    Un objet DeploymentPlanContributorContext qui fournit l'accès à tous les arguments spécifiés, au modèle des bases de données source et cible, aux propriétés de la build et aux fichiers d'extension, est passé à la méthode OnExecute. Dans cet exemple, nous obtenons le modèle, puis appelons des fonctions d'assistance aux informations de sortie concernant le modèle. Un ErrorManager à utiliser pour signaler toutes les erreurs qui se produisent est également passé à la méthode.

    Les autres types et méthodes intéressants sont les suivants : DataSchemaModel, ModelStore, ModelComparisonResult , DatabaseSchemaProvider , DeploymentPlanHandle et SchemaDeploymentOptions.

    Définissez ensuite la classe d'assistance qui examine les informations du plan de déploiement.

Pour ajouter la classe d'assistance qui génère le corps du rapport

  • Tout d'abord, ajoutez les squelettes de la classe d'assistance et ses méthodes en ajoutant le code suivant :

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

    Ensuite, ajoutez les membres de classe et les corps de méthode.

Pour ajouter les membres de classe

  • Dans l'éditeur de code, ajoutez le code suivant à la classe DeploymentReportWriter :

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

    Les types intéressants sont les suivants : DataSchemaModel , ModelComparisonResult et DeploymentStep.

    Ajoutez ensuite le corps au constructeur de classe.

Pour ajouter le corps de la méthode au constructeur

  • Ajoutez le code suivant en tant que corps du constructeur :

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

    Ajoutez ensuite le corps de la méthode à la méthode WriteReport.

Pour ajouter le corps de la méthode à la méthode WriteReport

  • Ajoutez le code suivant en tant que corps de la méthode WriteReport :

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

    Les types intéressants sont XmlWriter et XmlWriterSettings.

    Ajoutez ensuite le corps à la méthode ReportPlanOperations.

Pour ajouter le corps de la méthode à la méthode ReportPlanOperations

  • Ajoutez le code suivant en tant que corps de la méthode ReportPlanOperations :

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

    Les types intéressants sont les suivants : DeploymentStep , SqlRenameStep , SqlMoveSchemaStep , SqlTableMigrationStep , CreateElementStep , AlterElementStep et DropElementStep. Les types d'étape suivants sont des types d'étape supplémentaires qui ne sont pas affichés dans cet exemple : BeginPostDeploymentScriptStep, BeginPreDeploymentScriptStep, DeploymentScriptDomStep, DeploymentScriptStep, EndPostDeploymentScriptStep et EndPreDeploymentScriptStep. Vous pouvez également rechercher les étapes spécifiques à SQL Server : SqlBeginAltersStep, SqlBeginDropsStep, SqlBeginPreservationStep, SqlBeginTransactionStep, SqlEndAltersStep, SqlEndDropsStep, SqlEndPreservationStep, SqlEndTransactionStep, SqlFinalizeDatabaseAccessStep, SqlMoveSchemaStep, SqlPrintStep, SqlRenameStep et SqlTableMigrationStep.

    Ajoutez ensuite le corps de la méthode GetElementCategory.

Pour ajouter le corps de la méthode à la méthode GetElementCategory

  • Ajoutez le code suivant en tant que corps de la méthode GetElementCategory :

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

    Les types et les méthodes intéressants sont les suivants : DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices et GetElementTypeDescription .

    Ajoutez ensuite le corps de la méthode GetElementName.

Pour ajouter le corps de la méthode à la méthode GetElementName

  • Ajoutez le code suivant en tant que corps de la méthode GetElementName :

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

    Les types et les méthodes intéressants sont les suivants : DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices, GetElementName et ElementNameStyle.

    Enregistrez les modifications apportées à la classe. Générez ensuite la bibliothèque de classes.

Pour signer et générer l'assembly

  1. Dans le menu Projet, cliquez sur Propriétés MyDeploymentContributor.

  2. Cliquez sur l'onglet Signature.

  3. Cliquez sur Signer l'assembly.

  4. Dans la zone Choisir un fichier de clé de nom fort, cliquez sur <Nouveau>.

  5. Dans la boîte de dialogue Créer une clé de nom fort, en guise de nom du fichier de clé, tapez MaCléRéf.

  6. (Facultatif) Vous pouvez spécifier un mot de passe pour votre fichier de clé de nom fort.

  7. Cliquez sur OK.

  8. Dans le menu Fichier, cliquez sur Enregistrer tout.

  9. Dans le menu Générer, cliquez sur Générer la solution.

    Ensuite, vous devez installer et enregistrer l'assembly afin qu'il soit chargé lorsque vous déployez des projets de base de données.

Installer un collaborateur du déploiement

Pour installer un collaborateur du déploiement, vous devez effectuer les tâches suivantes :

  • Copier l'assembly et le fichier .pdb associé dans le dossier Extensions

  • Créer un fichier Extensions.xml pour inscrire le collaborateur de déploiement afin qu'il soit chargé lors du déploiement des projets de base de données

Pour installer l'assembly MyDeploymentContributor

  1. Créez un dossier nommé MesExtensions dans le dossier %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions.

  2. Copiez votre assembly signé (MyDeploymentContributor.dll) et le fichier .pdb associé (MyDeploymentContributor.pdb) dans le dossier %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MesExtensions.

    Notes

    Évitez de copier directement vos fichiers XML dans le dossier %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions. L'intérêt d'utiliser un sous-dossier est d'empêcher toute modification accidentelle apportée aux autres fichiers fournis avec Visual Studio Premium.

    Inscrivez maintenant votre assembly, qui est un type d'extension de fonctionnalité, pour le faire apparaître dans Visual Studio Premium.

Pour inscrire l'assembly MyDeploymentContributor

  1. Dans le menu Affichage, cliquez sur Autres fenêtres, puis cliquez sur Fenêtre Commande pour ouvrir la fenêtre Commande.

  2. Dans la fenêtre Commande, tapez le code suivant. Pour FilePath, substituez le chemin d'accès et le nom de votre fichier .dll compilé. Placez le chemin d'accès et le nom de fichier entre guillemets.

    Notes

    Par défaut, le chemin d'accès de votre fichier .dll compilé est CheminVotreSolution\bin\Debug ou CheminVotreSolution\bin\Release.

    ? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
    
    ? System.Reflection.Assembly.LoadFrom("FilePath").FullName
    
  3. Appuyez sur Entrée.

  4. Copiez la ligne résultante dans le Presse-papiers. Cette ligne doit se présenter comme suit :

    "MyDeploymentContributor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
    
  5. Ouvrez un éditeur de texte brut, tel que le Bloc-notes.

    Important

    Sur Windows Vista et Microsoft Windows Server 2008, ouvrez l'éditeur en tant qu'administrateur afin de pouvoir enregistrer le fichier dans votre dossier Program Files.

  6. Fournissez les informations suivantes, en spécifiant vos propres nom d'assembly, jeton de clé publique et type d'extension :

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

    Utilisez ce fichier XML pour inscrire la classe qui hérite de DeploymentPlanExecutor.

  7. Enregistrez le fichier sous le nom MyDeploymentContributor.extensions.xml dans le dossier %Program Files%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MesExtensions.

  8. Fermez Visual Studio.

    Vous allez ensuite déployer un projet de base de données pour tester votre collaborateur.

Tester son collaborateur du déploiement

Pour tester votre collaborateur du déploiement, vous devez effectuer les tâches suivantes :

  • Ajouter une propriété au fichier .dbproj que vous envisagez de déployer

  • Déployer le projet de base de données en utilisant MSBuild et en fournissant le paramètre approprié

Ajouter des propriétés au fichier projet de base de données (.dbproj)

Si vous souhaitez utiliser ce collaborateur du déploiement à partir de MSBuild, vous devez modifier le projet de base de données pour permettre aux utilisateurs de passer un paramètre via MSBuild. Pour mettre à jour votre projet de base de données, ouvrez-le dans l'éditeur de votre choix et ajoutez les instructions suivantes au fichier .dbproj entre le dernier nœud </ItemGroup> du fichier et le nœud </Project> final :

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

Après avoir mis à jour le fichier .dbproj, vous pouvez utiliser MSBuild pour passer les paramètres pour les générations à partir de la ligne de commande.

Déployer le projet de base de données

Pour déployer votre projet de base de données et générer un rapport de déploiement

  1. Ouvrez une invite de commandes Visual Studio. Dans le menu Démarrer, cliquez successivement sur Tous les programmes, Microsoft Visual Studio 2010, Visual Studio Tools, puis sur Invite de commandes de Visual Studio (2010).

  2. À l'invite de commandes, naviguez jusqu'au dossier qui contient votre projet de base de données.

  3. À l'invite de commandes, tapez la ligne de commande suivante :

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

    Remplacez MyDatabaseProject par le nom du projet de base de données que vous souhaitez générer. Si vous aviez modifié le projet après sa dernière génération, vous auriez pu utiliser /t:Build au lieu de /t:Rebuild.

  4. À l'invite de commandes, tapez la ligne de commande suivante :

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

    Remplacez MyDatabaseProject par le nom du projet de base de données que vous souhaitez déployer.

    Des résultats semblables aux suivants s'affichent :

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

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

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

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

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


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

Time Elapsed 00:00:04.02
  1. Ouvrez MyTargetDatabase.summary.xml et examinez-en le contenu.

    Le fichier ressemble à l'exemple suivant qui affiche un nouveau déploiement de base de données :

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

Notes

Si vous déployez un projet de base de données identique à la base de données cible, le rapport obtenu n'est pas très pertinent. Pour obtenir des résultats plus pertinents, déployez des modifications sur une base de données ou déployez une nouvelle base de données.

  1. Ouvrez MyTargetDatabase.details.xml et examinez-en le contenu.

    Une petite section du fichier de détails affiche les entrées et le script qui créent le schéma Sales, qui impriment un message concernant la création d'une table et qui créent la table :

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

En analysant le plan de déploiement lors de son exécution, vous pouvez signaler des informations contenues dans le déploiement et pouvez également prendre des mesures supplémentaires en fonction des étapes de ce plan.

Étapes suivantes

Vous pouvez créer des outils supplémentaires pour exécuter le traitement des fichiers XML de sortie. Il s'agit juste d'un exemple de DeploymentPlanExecutor. Vous pouvez également créer un DeploymentPlanModifier pour modifier un plan de déploiement avant qu'il ne soit exécuté.

Voir aussi

Concepts

Extension des fonctionnalités de base de données de Visual Studio

Autres ressources

Personnaliser la génération et le déploiement d'une base de données à l'aide de collaborateurs de génération et de déploiement

Procédure pas à pas : étendre une build de projet de base de données pour générer des statistiques de modèle

Procédure pas à pas : étendre un déploiement de projet de base de données pour modifier le plan de déploiement