Freigeben über


Leitfaden: Erweiterung der Datenbankprojektbereitstellung für die Analyse des Bereitstellungsplans

Sie können Bereitstellungsmitwirkende erstellen, um benutzerdefinierte Aktionen auszuführen, wenn Sie ein SQL-Projekt bereitstellen. Sie können entweder einen DeploymentPlanModifier oder einen DeploymentPlanExecutor erstellen. Verwenden Sie einen DeploymentPlanModifier, um den Plan zu ändern, bevor er ausgeführt wird, und einen DeploymentPlanExecutor, um Vorgänge auszuführen, während der Plan ausgeführt wird. In dieser exemplarischen Vorgehensweise erstellen Sie einen DeploymentPlanExecutor namens DeploymentUpdateReportContributor, der einen Bericht über die Aktionen erstellt, die beim Bereitstellen eines Datenbankprojekts ausgeführt werden. Da dieser Buildmitwirkender einen Parameter akzeptiert, um zu steuern, ob der Bericht generiert wird, müssen Sie einen weiteren erforderlichen Schritt ausführen.

In diesem Durchlauf führen Sie die folgenden wichtigen Aufgaben aus:

Voraussetzungen

Zum Abschließen dieser exemplarischen Vorgehensweise benötigen Sie Folgendes:

  • Sie müssen eine Version von Visual Studio installiert haben, die SQL Server Data Tools (SSDT) enthält und die C#- oder VB-Entwicklung unterstützt.
  • Sie müssen über ein SQL-Projekt verfügen, das SQL-Objekte enthält.
  • Eine Instanz von SQL Server, für die Sie ein Datenbankprojekt bereitstellen können.

Hinweis

Diese exemplarische Vorgehensweise richtet sich an Benutzer, die bereits mit den SQL-Features von SSDT vertraut sind. Außerdem wird erwartet, dass Sie mit grundlegenden Visual Studio-Konzepten vertraut sind, z. B. wie Sie eine Klassenbibliothek erstellen und wie Sie den Code-Editor verwenden, um einer Klasse Code hinzuzufügen.

Erstellen eines Bereitstellungsmitwirkenden

Zum Erstellen eines Bereitstellungsmitwirkenden müssen Sie die folgenden Aufgaben ausführen:

  • Erstellen Sie ein Klassenbibliotheksprojekt, und fügen Sie erforderliche Verweise hinzu.

  • Definieren Sie eine Klasse mit dem Namen DeploymentUpdateReportContributor, die von DeploymentPlanExecutor erbt.

  • Überschreiben Sie die OnExecute-Methode.

  • Fügen Sie eine private Hilfsklasse hinzu.

  • Erstellen Sie die resultierende Zusammenstellung.

Erstellen eines Klassenbibliotheksprojekts

  1. Erstellen Sie ein Visual Basic- oder C#-Klassenbibliotheksprojekt namens "MyDeploymentContributor".

  2. Benennen Sie die Datei "Class1.cs" in "DeploymentUpdateReportContributor.cs" um.

  3. Klicken Sie im Projekt-Explorer mit der rechten Maustaste auf den Projektknoten und wählen dann "Verweis hinzufügen" aus.

  4. Wählen Sie " System.ComponentModel.Composition " auf der Registerkarte "Frameworks" aus.

  5. Fügen Sie erforderliche SQL-Verweise hinzu: Klicken Sie mit der rechten Maustaste auf den Projektknoten, und wählen Sie dann "Verweis hinzufügen" aus. Wählen Sie "Durchsuchen" aus, und navigieren Sie zum Ordner "C:\Programme (x86)\Microsoft SQL Server\110\DAC\Bin ". Wählen Sie die Microsoft.SqlServer.Dac.dll, Microsoft.SqlServer.Dac.Extensions.dllund Microsoft.Data.Tools.Schema.Sql.dll Einträge aus, wählen Sie "Hinzufügen" und dann "OK" aus.

    Beginnen Sie als Nächstes mit dem Hinzufügen von Code zur Klasse.

Definieren der DeploymentUpdateReportContributor-Klasse

  1. Aktualisieren Sie im Code-Editor die DeploymentUpdateReportContributor.cs Datei so, dass sie mit den folgenden using-Anweisungen übereinstimmt:

    using System;
    using System.IO;
    using System.Text;
    using System.Xml;
    using Microsoft.SqlServer.Dac.Deployment;
    using Microsoft.SqlServer.Dac.Extensibility;
    using Microsoft.SqlServer.Dac.Model;
    
  2. Aktualisieren Sie die Klassendefinition so, dass sie dem folgenden Code entspricht:

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

    Jetzt haben Sie Ihren Bereitstellungsmitwirkenden definiert, der von DeploymentPlanExecutor erbt. Während der Build- und Bereitstellungsprozesse werden benutzerdefinierte Mitwirkende aus einem Standarderweiterungsverzeichnis geladen. Die Mitwirkenden des Bereitstellungsplans werden durch ein ExportDeploymentPlanExecutor-Attribut identifiziert.

    Dieses Attribut ist erforderlich, damit Mitwirkende ermittelt werden können. Er sollte dem folgenden Code ähneln:

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

    In diesem Fall sollte der erste Parameter für das Attribut ein eindeutiger Bezeichner sein – dies wird verwendet, um Ihren Mitwirkenden in Projektdateien zu identifizieren. Eine bewährte Methode besteht darin, den Namespace Ihrer Bibliothek – in diesem Beispiel MyDeploymentContributor – mit dem Klassennamen – in diesem Beispiel DeploymentUpdateReportContributor – zu kombinieren, um den Bezeichner zu erzeugen.

  3. Fügen Sie als Nächstes das folgende Mitglied hinzu, das Sie verwenden, um diesem Anbieter die Annahme eines Befehlszeilenparameters zu ermöglichen:

    public const string GenerateUpdateReport = "DeploymentUpdateReportContributor.GenerateUpdateReport";
    

    Mit diesem Element kann der Benutzer angeben, ob der Bericht mithilfe der Option GenerateUpdateReport generiert werden soll.

    Als Nächstes überschreiben Sie die OnExecute-Methode, um den Code hinzuzufügen, den Sie ausführen möchten, wenn ein Datenbankprojekt bereitgestellt wird.

Überschreiben von OnExecute

  • Fügen Sie der DeploymentUpdateReportContributor-Klasse die folgende Methode hinzu:

    /// <summary>
            /// Override the OnExecute method to perform actions when you execute the deployment plan for
            /// a database project.
            /// </summary>
            protected override void OnExecute(DeploymentPlanContributorContext context)
            {
                // determine whether the user specified a report is to be generated
                bool generateReport = false;
                string generateReportValue;
                if (context.Arguments.TryGetValue(GenerateUpdateReport, out generateReportValue) == false)
                {
                    // couldn't find the GenerateUpdateReport argument, so do not generate
                    generateReport = false;
                }
                else
                {
                    // GenerateUpdateReport argument was specified, try to parse the value
                    if (bool.TryParse(generateReportValue, out generateReport))
                    {
                        // if we end up here, the value for the argument was not valid.
                        // default is false, so do nothing.
                    }
                }
    
                if (generateReport == false)
                {
                    // if user does not want to generate a report, we are done
                    return;
                }
    
                // We output to the same directory where the deployment script
                // is output or to the current directory
                string reportPrefix = context.Options.TargetDatabaseName;
                string reportPath;
                if (string.IsNullOrEmpty(context.DeploymentScriptPath))
                {
                    reportPath = Environment.CurrentDirectory;
                }
                else
                {
                    reportPath = Path.GetDirectoryName(context.DeploymentScriptPath);
                }
                FileInfo summaryReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".summary.xml"));
                FileInfo detailsReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".details.xml"));
    
                // Generate the reports by using the helper class DeploymentReportWriter
                DeploymentReportWriter writer = new DeploymentReportWriter(context);
                writer.WriteReport(summaryReportFile);
                writer.IncludeScripts = true;
                writer.WriteReport(detailsReportFile);
    
                string msg = "Deployment reports ->"
                    + Environment.NewLine + summaryReportFile.FullName
                    + Environment.NewLine + detailsReportFile.FullName;
    
                ExtensibilityError reportMsg = new ExtensibilityError(msg, Severity.Message);
                base.PublishMessage(reportMsg);
            }
        /// <summary>
        /// Override the OnExecute method to perform actions when you execute the deployment plan for
        /// a database project.
        /// </summary>
            protected override void OnExecute(DeploymentPlanContributorContext context)
            {
                // determine whether the user specified a report is to be generated
                bool generateReport = false;
                string generateReportValue;
                if (context.Arguments.TryGetValue(GenerateUpdateReport, out generateReportValue) == false)
                {
                    // couldn't find the GenerateUpdateReport argument, so do not generate
                    generateReport = false;
                }
                else
                {
                    // GenerateUpdateReport argument was specified, try to parse the value
                    if (bool.TryParse(generateReportValue, out generateReport))
                    {
                        // if we end up here, the value for the argument was not valid.
                        // default is false, so do nothing.
                    }
                }
    
                if (generateReport == false)
                {
                    // if user does not want to generate a report, we are done
                    return;
                }
    
                // We output to the same directory where the deployment script
                // is output or to the current directory
                string reportPrefix = context.Options.TargetDatabaseName;
                string reportPath;
                if (string.IsNullOrEmpty(context.DeploymentScriptPath))
                {
                    reportPath = Environment.CurrentDirectory;
                }
                else
                {
                    reportPath = Path.GetDirectoryName(context.DeploymentScriptPath);
                }
                FileInfo summaryReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".summary.xml"));
                FileInfo detailsReportFile = new FileInfo(Path.Combine(reportPath, reportPrefix + ".details.xml"));
    
                // Generate the reports by using the helper class DeploymentReportWriter
                DeploymentReportWriter writer = new DeploymentReportWriter(context);
                writer.WriteReport(summaryReportFile);
                writer.IncludeScripts = true;
                writer.WriteReport(detailsReportFile);
    
                string msg = "Deployment reports ->"
                    + Environment.NewLine + summaryReportFile.FullName
                    + Environment.NewLine + detailsReportFile.FullName;
    
                DataSchemaError reportMsg = new DataSchemaError(msg, ErrorSeverity.Message);
                base.PublishMessage(reportMsg);
            }
    

    Die OnExecute-Methode wird einDeploymentPlanContributorContext-Objekt übergeben, das Zugriff auf alle angegebenen Argumente, das Quell- und Zieldatenbankmodell, Buildeigenschaften und Erweiterungsdateien bietet. In diesem Beispiel rufen wir das Modell ab und rufen dann Hilfsfunktionen auf, um Informationen zum Modell auszugeben. Wir verwenden die PublishMessage-Hilfsmethode für die Basisklasse, um alle aufgetretenen Fehler zu melden.

    Weitere Interessante Typen und Methoden sind : TSqlModel, ModelComparisonResult, DeploymentPlanHandle und SqlDeploymentOptions.

    Als Nächstes definieren Sie die Hilfsklasse, die in die Details des Bereitstellungsplans eingeht.

Hinzufügen der Hilfsklasse, die den Berichtstext generiert

  • Fügen Sie die Hilfsklasse und die zugehörigen Methoden hinzu, indem Sie den folgenden Code hinzufügen:

    /// <summary>
            /// This class is used to generate a deployment
            /// report.
            /// </summary>
            private class DeploymentReportWriter
            {
                readonly TSqlModel _sourceModel;
                readonly ModelComparisonResult _diff;
                readonly DeploymentStep _planHead;
    
                /// <summary>
                /// The constructor accepts the same context info
                /// that was passed to the OnExecute method of the
                /// deployment contributor.
                /// </summary>
                public DeploymentReportWriter(DeploymentPlanContributorContext context)
                {
                    if (context == null)
                    {
                        throw new ArgumentNullException("context");
                    }
    
                    // save the source model, source/target differences,
                    // and the beginning of the deployment plan.
                    _sourceModel = context.Source;
                    _diff = context.ComparisonResult;
                    _planHead = context.PlanHandle.Head;
                }
                /// <summary>
                /// Property indicating whether script bodies
                /// should be included in the report.
                /// </summary>
                public bool IncludeScripts { get; set; }
    
                /// <summary>
                /// Drives the report generation, opening files,
                /// writing the beginning and ending report elements,
                /// and calling helper methods to report on the
                /// plan operations.
                /// </summary>
                internal void WriteReport(FileInfo reportFile)
                {// Assumes that we have a valid report file
                    if (reportFile == null)
                    {
                        throw new ArgumentNullException("reportFile");
                    }
    
                    // set up the XML writer
                    XmlWriterSettings xmlws = new XmlWriterSettings();
                    // Indentation makes it a bit more readable
                    xmlws.Indent = true;
                    FileStream fs = new FileStream(reportFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    XmlWriter xmlw = XmlWriter.Create(fs, xmlws);
    
                    try
                    {
                        xmlw.WriteStartDocument(true);
                        xmlw.WriteStartElement("DeploymentReport");
    
                        // Summary report of the operations that
                        // are contained in the plan.
                        ReportPlanOperations(xmlw);
    
                        // You could add a method call here
                        // to produce a detailed listing of the
                        // differences between the source and
                        // target model.
                        xmlw.WriteEndElement();
                        xmlw.WriteEndDocument();
                        xmlw.Flush();
                        fs.Flush();
                    }
                    finally
                    {
                        xmlw.Close();
                        fs.Dispose();
                    }
                }
    
                /// <summary>
                /// Writes details for the various operation types
                /// that could be contained in the deployment plan.
                /// Optionally writes script bodies, depending on
                /// the value of the IncludeScripts property.
                /// </summary>
                private void ReportPlanOperations(XmlWriter xmlw)
                {// write the node to indicate the start
                    // of the list of operations.
                    xmlw.WriteStartElement("Operations");
    
                    // Loop through the steps in the plan,
                    // starting at the beginning.
                    DeploymentStep currentStep = _planHead;
                    while (currentStep != null)
                    {
                        // Report the type of step
                        xmlw.WriteStartElement(currentStep.GetType().Name);
    
                        // based on the type of step, report
                        // the relevant information.
                        // Note that this procedure only handles
                        // a subset of all step types.
                        if (currentStep is SqlRenameStep)
                        {
                            SqlRenameStep renameStep = (SqlRenameStep)currentStep;
                            xmlw.WriteAttributeString("OriginalName", renameStep.OldName);
                            xmlw.WriteAttributeString("NewName", renameStep.NewName);
                            xmlw.WriteAttributeString("Category", GetElementCategory(renameStep.RenamedElement));
                        }
                        else if (currentStep is SqlMoveSchemaStep)
                        {
                            SqlMoveSchemaStep moveStep = (SqlMoveSchemaStep)currentStep;
                            xmlw.WriteAttributeString("OriginalName", moveStep.PreviousName);
                            xmlw.WriteAttributeString("NewSchema", moveStep.NewSchema);
                            xmlw.WriteAttributeString("Category", GetElementCategory(moveStep.MovedElement));
                        }
                        else if (currentStep is SqlTableMigrationStep)
                        {
                            SqlTableMigrationStep dmStep = (SqlTableMigrationStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(dmStep.SourceTable));
                            xmlw.WriteAttributeString("Category", GetElementCategory(dmStep.SourceElement));
                        }
                        else if (currentStep is CreateElementStep)
                        {
                            CreateElementStep createStep = (CreateElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(createStep.SourceElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(createStep.SourceElement));
                        }
                        else if (currentStep is AlterElementStep)
                        {
                            AlterElementStep alterStep = (AlterElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(alterStep.SourceElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(alterStep.SourceElement));
                        }
                        else if (currentStep is DropElementStep)
                        {
                            DropElementStep dropStep = (DropElementStep)currentStep;
                            xmlw.WriteAttributeString("Name", GetElementName(dropStep.TargetElement));
                            xmlw.WriteAttributeString("Category", GetElementCategory(dropStep.TargetElement));
                        }
    
                        // If the script bodies are to be included,
                        // add them to the report.
                        if (this.IncludeScripts)
                        {
                            using (StringWriter sw = new StringWriter())
                            {
                                currentStep.GenerateBatchScript(sw);
                                string tsqlBody = sw.ToString();
                                if (string.IsNullOrEmpty(tsqlBody) == false)
                                {
                                    xmlw.WriteCData(tsqlBody);
                                }
                            }
                        }
    
                        // close off the current step
                        xmlw.WriteEndElement();
                        currentStep = currentStep.Next;
                    }
                    xmlw.WriteEndElement();
                }
    
                /// <summary>
                /// Returns the category of the specified element
                /// in the source model
                /// </summary>
                private string GetElementCategory(TSqlObject element)
                {
                    return element.ObjectType.Name;
                }
    
                /// <summary>
                /// Returns the name of the specified element
                /// in the source model
                /// </summary>
                private static string GetElementName(TSqlObject element)
                {
                    StringBuilder name = new StringBuilder();
                    if (element.Name.HasExternalParts)
                    {
                        foreach (string part in element.Name.ExternalParts)
                        {
                            if (name.Length > 0)
                            {
                                name.Append('.');
                            }
                            name.AppendFormat("[{0}]", part);
                        }
                    }
    
                    foreach (string part in element.Name.Parts)
                    {
                        if (name.Length > 0)
                        {
                            name.Append('.');
                        }
                        name.AppendFormat("[{0}]", part);
                    }
    
                    return name.ToString();
                }
            }        /// <summary>
            /// This class is used to generate a deployment
            /// report.
            /// </summary>
            private class DeploymentReportWriter
            {
                /// <summary>
                /// The constructor accepts the same context info
                /// that was passed to the OnExecute method of the
                /// deployment contributor.
                /// </summary>
                public DeploymentReportWriter(DeploymentPlanContributorContext context)
                {
               }
                /// <summary>
                /// Property indicating whether script bodies
                /// should be included in the report.
                /// </summary>
                public bool IncludeScripts { get; set; }
    
                /// <summary>
                /// Drives the report generation, opening files,
                /// writing the beginning and ending report elements,
                /// and calling helper methods to report on the
                /// plan operations.
                /// </summary>
                internal void WriteReport(FileInfo reportFile)
                {
                }
    
                /// <summary>
                /// Writes details for the various operation types
                /// that could be contained in the deployment plan.
                /// Optionally writes script bodies, depending on
                /// the value of the IncludeScripts property.
                /// </summary>
                private void ReportPlanOperations(XmlWriter xmlw)
                {
                }
    
                /// <summary>
                /// Returns the category of the specified element
                /// in the source model
                /// </summary>
                private string GetElementCategory(IModelElement element)
                {
                }
    
                /// <summary>
                /// Returns the name of the specified element
                /// in the source model
                /// </summary>
                private string GetElementName(IModelElement element)
                {
                }
            }
    
  • Speichern Sie die Änderungen an der Klassendatei. Auf mehrere nützliche Typen wird in der Hilfsklasse verwiesen:

    Codebereich Nützliche Typen
    Klassenmitglieder TSqlModel, ModelComparisonResult, DeploymentStep
    WriteReport-Methode XmlWriter und XmlWriterSettings
    ReportPlanOperations-Methode Interessante Typen sind: DeploymentStep, SqlRenameStep, SqlMoveSchemaStep, SqlTableMigrationStep, CreateElementStep, AlterElementStep, DropElementStep.

    Es gibt mehrere weitere Schritte – eine vollständige Liste der Schritte finden Sie in der API-Dokumentation.
    GetElementCategory TSqlObject
    GetElementName TSqlObject

    Als Nächstes erstellen Sie die Klassenbibliothek.

Signieren und Erstellen der Assembly

  1. Wählen Sie im Menü "Projekt" die Option "MyDeploymentContributor"-Eigenschaften aus.

  2. Wählen Sie die Registerkarte " Signieren" aus .

  3. Wählen Sie "die Assembly signieren" aus.

  4. Wählen Sie in "Wählen Sie eine Datei mit starkem Namenschlüssel" aus, und wählen Sie "Neu"< aus>.

  5. Geben Sie im Dialogfeld Erstellen Sie den starken Namen-Schlüssel unter MyRefKey den Namen ein.

  6. (optional) Sie können ein Kennwort für Ihre starke Namensschlüsseldatei angeben.

  7. Wählen Sie OK aus.

  8. Wählen Sie im Menü "Datei " die Option "Alle speichern" aus.

  9. Wählen Sie im Menü Erstellen die Option Lösung erstellen.

Als Nächstes müssen Sie die Assembly installieren, damit sie beim Erstellen und Bereitstellen von SQL-Projekten geladen wird.

Installieren eines Bereitstellungsmitwirkenden

Um einen Bereitstellungsmitwirkenden zu installieren, müssen Sie die Assembly und die zugehörige .pdb Datei in den Ordner "Erweiterungen" kopieren.

Installieren der MyDeploymentContributor-Assembly

  • Als Nächstes kopieren Sie die Assemblyinformationen in das Verzeichnis "Erweiterungen". Wenn Visual Studio gestartet wird, werden alle Erweiterungen in den %ProgramFiles%\Microsoft SQL Server\110\DAC\Bin\Extensions Verzeichnis- und Unterverzeichnissen identifiziert und zur Verwendung zur Verfügung gestellt:

  • Kopieren Sie die MyDeploymentContributor.dll Assemblydatei aus dem Ausgabeverzeichnis in das %ProgramFiles%\Microsoft SQL Server\110\DAC\Bin\Extensions Verzeichnis. Standardmäßig lautet .dll der Pfad der kompilierten YourSolutionPath\YourProjectPath\bin\Debug Datei oder YourSolutionPath\YourProjectPath\bin\Release.

Testen Sie Ihren Bereitstellungsmitwirkenden

Um Ihren Bereitstellungsmitwirkenden zu testen, müssen Sie die folgenden Aufgaben ausführen:

  • Fügen Sie der .sqlproj Datei, die Sie bereitstellen möchten, Eigenschaften hinzu.

  • Stellen Sie das Projekt mithilfe von MSBuild bereit und stellen Sie den entsprechenden Parameter bereit.

Hinzufügen von Eigenschaften zur SQL-Projektdatei (SQLPROJ)

Sie müssen die SQL-Projektdatei immer aktualisieren, um die ID der Mitwirkenden anzugeben, deren Aktionen Sie ausführen möchten. Darüber hinaus, da dieser Mitwirkende ein Argument "GenerateUpdateReport" erwartet, muss dies als Mitwirkenderargument angegeben werden.

Sie können dies auf eine von zwei Arten tun. Sie können die .sqlproj Datei manuell ändern, um die erforderlichen Argumente hinzuzufügen. Sie können dies tun, wenn Ihr Mitwirkender keine Für die Konfiguration erforderlichen Mitwirkendenargumente hat oder wenn Sie nicht beabsichtigen, den Mitwirkenden in einer großen Anzahl von Projekten wiederzuverwenden. Wenn Sie diese Option auswählen, fügen Sie die folgenden Anweisungen nach dem ersten Importknoten in der Datei in die Datei .sqlproj ein:

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

Die zweite Methode besteht darin, eine Zieldatei zu erstellen, die die erforderlichen Mitwirkendenargumente enthält. Dies ist nützlich, wenn Sie denselben Mitwirkenden für mehrere Projekte verwenden und über erforderliche Mitwirkendeargumente verfügen, da sie die Standardwerte enthält. Erstellen Sie in diesem Fall eine Zieldatei im MSBuild-Erweiterungspfad.

  1. Navigiere zu %ProgramFiles%\MSBuild.

  2. Erstellen Sie einen neuen Ordner MyContributors , in dem Ihre Zieldateien gespeichert werden.

  3. Erstellen Sie eine neue Datei MyContributors.targets in diesem Verzeichnis, fügen Sie dem Verzeichnis den folgenden Text hinzu, und speichern Sie die Datei:

    <?xml version="1.0" encoding="utf-8"?>
    
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
    <DeploymentContributors>$(DeploymentContributors);MyDeploymentContributor.DeploymentUpdateReportContributor</DeploymentContributors>
    <ContributorArguments Condition="'$(Configuration)' == 'Debug'">$(ContributorArguments); DeploymentUpdateReportContributor.GenerateUpdateReport=true;</ContributorArguments>
      </PropertyGroup>
    </Project>
    
  4. Importieren Sie in der .sqlproj-Datei für jedes Projekt, das Sie ausführen möchten, die Zieldatei, indem Sie der .sqlproj-Datei nach dem <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />-Knoten die folgende Anweisung hinzufügen:

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

Nachdem Sie eine dieser Ansätze befolgt haben, können Sie MSBuild verwenden, um die Parameter für Befehlszeilenbuilds zu übergeben.

Hinweis

Sie müssen die Eigenschaft "DeploymentContributors" immer aktualisieren, um Ihre Mitwirkenden-ID anzugeben. Dies ist die gleiche ID, die im Attribut "ExportDeploymentPlanExecutor" in Ihrer Mitwirkendenquelldatei verwendet wird. Ohne diese Komponente wird Ihr Skript beim Erstellen des Projekts nicht ausgeführt. Die Eigenschaft "ContributorArguments" muss nur aktualisiert werden, wenn Argumente vorliegen, die für die Ausführung des Mitwirkenden notwendig sind.

Bereitstellen des Datenbankprojekts

Ihr Projekt kann in Visual Studio als normal veröffentlicht oder bereitgestellt werden. Öffnen Sie eine Lösung, die Ihr SQL-Projekt enthält, und wählen Sie "Veröffentlichen..." aus dem Kontextmenü des Projekts, das Sie durch einen Rechtsklick öffnen. Oder verwenden Sie F5 für eine Debug-Bereitstellung auf LocalDB. In diesem Beispiel verwenden wir "Veröffentlichen..." Dialog zum Generieren eines Bereitstellungsskripts.

Stellen Sie Ihr SQL-Projekt bereit und erstellen Sie ein Bereitstellungsprotokoll.

  1. Öffnen Sie Visual Studio, und öffnen Sie die Projektmappe, die Ihr SQL-Projekt enthält.

  2. Wählen Sie Ihr Projekt aus, und drücken Sie "F5", um ein Debugging durchzuführen. Hinweis: Da das ContributorArguments-Element nur enthalten ist, wenn die Konfiguration "Debug" lautet, wird der Bereitstellungsbericht nur für Debugbereitstellungen generiert. Um dies zu ändern, entfernen Sie die Condition="'$(Configuration)' == 'Debug'"-Anweisung aus der ContributorArguments-Definition.

  3. Die Ausgabe, z. B. das folgende Beispiel, sollte im Ausgabefenster vorhanden sein:

    ------ Deploy started: Project: Database1, Configuration: Debug Any CPU ------
    Finished verifying cached model in 00:00:00
    Deployment reports ->
    
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.summary.xml
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyTargetDatabase.details.xml
    
      Deployment script generated to:
      C:\Users\UserName\Documents\Visual Studio 2012\Projects\MyDatabaseProject\MyDatabaseProject\sql\debug\MyDatabaseProject.sql
    
  4. Öffnen Sie MyTargetDatabase.summary.xml, und überprüfen Sie den Inhalt. Die Datei ähnelt dem folgenden Beispiel, das eine neue Datenbankbereitstellung zeigt:

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

    Hinweis

    Wenn Sie ein Datenbankprojekt bereitstellen, das mit der Zieldatenbank identisch ist, ist der resultierende Bericht nicht sehr aussagekräftig. Um aussagekräftigere Ergebnisse zu erzielen, stellen Sie entweder Änderungen an einer Datenbank bereit oder stellen Sie eine neue Datenbank bereit.

  5. Öffnen Sie MyTargetDatabase.details.xml, und überprüfen Sie den Inhalt. In einem kleinen Abschnitt der Detaildatei werden die Einträge und skripts angezeigt, mit denen das Schema "Sales" erstellt wird, in dem eine Meldung zum Erstellen einer Tabelle gedruckt wird und die Tabelle erstellt wird:

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

    Indem Sie den Bereitstellungsplan während der Ausführung analysieren, können Sie alle Informationen melden, die in der Bereitstellung enthalten sind, und basierend auf den Schritten in diesem Plan weitere Aktionen ausführen.