Exemplarische Vorgehensweise: Erweitern der Bereitstellung von Datenbankprojekten zum Analysieren des Bereitstellungsplans
Sie können Bereitstellungscontributors erstellen, damit beim Bereitstellen eines Datenbankprojekts benutzerdefinierte Aktionen ausgeführt werden. Sie können entweder einen DeploymentPlanModifier oder einen DeploymentPlanExecutor erstellen. Ein DeploymentPlanModifier dient zum Ändern des Plans vor dessen Ausführung. Ein DeploymentPlanExecutor dient zum Ausführen von Vorgängen während der Planausführung. In dieser exemplarischen Vorgehensweise wird ein DeploymentPlanExecutor mit dem Namen "DeploymentUpdateReportContributor" erstellt, durch den ein Bericht zu den Aktionen erstellt wird, die beim Bereitstellen eines Datenbankprojekts ausgeführt werden. Da von diesem Buildcontributor ein Parameter akzeptiert wird, um zu steuern, ob der Bericht generiert wird, ist ein zusätzlicher Schritt erforderlich.
Im Verlauf dieser exemplarischen Vorgehensweise werden die folgenden Hauptaufgaben ausgeführt:
Erstellen eines Bereitstellungscontributors vom Typ "DeploymentPlanExecutor"
Installieren des Bereitstellungscontributors
Testen des Bereitstellungscontributors
Vorbereitungsmaßnahmen
Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie die folgenden Komponenten:
Installation von Visual Studio 2010 Premium oder Visual Studio 2010 Ultimate auf dem Computer
Ein Datenbankprojekt mit Datenbankobjekten
Eine Instanz von SQL Server, für die ein Datenbankprojekt bereitgestellt werden kann
Tipp
Diese exemplarische Vorgehensweise richtet sich an Benutzer, die bereits mit den Datenbankfunktionen von Visual Studio vertraut sind. Sie sollten außerdem mit grundlegenden Konzepten von Visual Studio wie dem Erstellen einer Klassenbibliothek und dem Verwenden des Code-Editors zum Hinzufügen von Code zu einer Klasse vertraut sein.
Erstellen eines Bereitstellungscontributors
Führen Sie zum Erstellen eines Bereitstellungscontributors die folgenden Aufgaben aus:
Erstellen eines Klassenbibliothekprojekts und Hinzufügen erforderlicher Verweise
Definieren einer Klasse mit dem Namen "DeploymentUpdateReportContributor" und Vererbung von DeploymentPlanExecutor
Überschreiben der OnPopulateArguments-Methode und der OnExecute-Methode
Hinzufügen einer privaten Hilfsklasse
Erstellen der resultierenden Assembly
So erstellen Sie ein Klassenbibliotheksprojekt
Erstellen Sie ein Visual Basic- oder ein Visual C#-Klassenbibliothekprojekt mit dem Namen "MyDeploymentContributor".
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Verweise, und klicken Sie anschließend auf Verweis hinzufügen.
Klicken Sie auf die Registerkarte .NET.
Markieren Sie die Einträge Microsoft.Data.Schema und Microsoft.Data.Schema.Sql, und klicken Sie auf OK.
Fügen Sie der Klasse nun Code hinzu.
So definieren Sie die DeploymentUpdateReportContributor-Klasse
Aktualisieren Sie im Code-Editor die Datei "class1.cs" mit den folgenden using- oder Imports-Anweisungen:
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
Aktualisieren Sie die Klassendefinition wie folgt:
[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
Sie haben nun den Buildcontributor definiert und mit dem Attribut angegeben, dass dieser Contributor mit jedem beliebigen Datenbankschema-Anbieter kompatibel ist, der von SqlDatabaseSchemaProvider erbt.
Fügen Sie nun den folgenden Member hinzu, mit dem diesem Anbieter das Akzeptieren eines Befehlszeilenparameters ermöglicht wird:
private const string GenerateUpdateReport = "GenerateUpdateReport";
Dim GenerateUpdateReport As String = "GenerateUpdateReport"
Dank dieses Members kann der Benutzer mithilfe der Option "GenerateUpdateReport" angeben, ob der Bericht generiert werden soll.
Im nächsten Schritt wird die OnPopulateArguments-Methode überschrieben, um die Liste mit den Argumenten zu erstellen, die an den Bereitstellungscontributor übergeben werden sollen.
So überschreiben Sie OnPopulateArguments
Fügen Sie der DeploymentUpdateReportContributor-Klasse die folgende Überschreibungsmethode hinzu:
/// <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
Sie erstellen ein ContributorArgumentConfiguration-Objekte und fügen es der Argumentliste hinzu. Standardmäßig wird der Bericht generiert, wenn Sie einen Debugbuild generieren.
Im nächsten Schritt wird die OnExecute-Methode überschrieben, um den Code hinzuzufügen, der beim Bereitstellen eines Datenbankprojekts ausgeführt werden soll.
So überschreiben Sie 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 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
An die OnExecute-Methode wird ein DeploymentPlanContributorContext-Objekt übergeben, das den Zugriff auf beliebige angegebene Argumente, auf das Quell- und Zieldatenbankmodell, auf Buildeigenschaften sowie auf Erweiterungsdateien ermöglicht. In diesem Beispiel wird zunächst das Modell abgerufen. Anschließend werden Hilfsfunktionen aufgerufen, um Informationen zum Modell auszugeben. An die Methode wird auch ein ErrorManager übergeben, um die aufgetretenen Fehler zu melden.
Weitere relevante Typen und Methoden: DataSchemaModel, ModelStore, ModelComparisonResult, DatabaseSchemaProvider, DeploymentPlanHandle and SchemaDeploymentOptions.
Im nächsten Schritt wird die Hilfsklasse definiert, um in die Details des Bereitstellungsplans vorzudringen.
So fügen Sie die Hilfsklasse hinzu, von der der Hauptteil des Berichts generiert wird
Fügen Sie zunächst die Skelette der Hilfsklasse und deren Methoden hinzu, indem Sie den folgenden Code hinzufügen:
/// <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
Speichern Sie die Änderungen in der Datei "Class1.cs".
Fügen Sie als Nächstes die Klassenmember und Methodentexte hinzu.
So fügen Sie die Klassenmember hinzu
Fügen Sie der DeploymentReportWriter-Klasse im Code-Editor den folgenden Code hinzu:
readonly DataSchemaModel _sourceModel; readonly ModelComparisonResult _diff; readonly DeploymentStep _planHead;
ReadOnly _sourceModel As DataSchemaModel ReadOnly _diff As ModelComparisonResult ReadOnly _planHead As DeploymentStep
Relevante Typen: DataSchemaModel, ModelComparisonResult und DeploymentStep.
Im nächsten Schritt wird der Text dem Klassenkonstruktor hinzugefügt.
So fügen dem Konstruktor den Methodentext hinzu
Fügen Sie den folgenden Code als Konstruktortext hinzu:
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
Im nächsten Schritt wird der Methodentext der WriteReport-Methode hinzugefügt.
So fügen Sie den Methodentext der OutputResult-Methode hinzu
Fügen Sie den folgenden Code als Text der WriteReport-Methode hinzu:
// 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
Relevante Typen: XmlWriter und XmlWriterSettings.
Im nächsten Schritt wird der Methodentext der ReportPlanOperations-Methode hinzugefügt.
So fügen Sie den Methodentext der ReportPlanOperations-Methode hinzu:
Fügen Sie den folgenden Code als Text der ReportPlanOperations-Methode hinzu:
// 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()
Relevante Typen: DeploymentStep, SqlRenameStep, SqlMoveSchemaStep, SqlTableMigrationStep, CreateElementStep, AlterElementStep und DropElementStep. Weitere Schritttypen, die in diesem Beispiel nicht erläutert wurden: BeginPostDeploymentScriptStep, BeginPreDeploymentScriptStep, DeploymentScriptDomStep, DeploymentScriptStep, EndPostDeploymentScriptStep und EndPreDeploymentScriptStep. Sie können auch nach den SQL Server-spezifischen Schritten suchen: SqlBeginAltersStep, SqlBeginDropsStep, SqlBeginPreservationStep, SqlBeginTransactionStep, SqlEndAltersStep, SqlEndDropsStep, SqlEndPreservationStep, SqlEndTransactionStep, SqlFinalizeDatabaseAccessStep, SqlMoveSchemaStep, SqlPrintStep, SqlRenameStep und SqlTableMigrationStep.
Im nächsten Schritt wird der Text der GetElementCategory-Methode hinzugefügt.
So fügen Sie den Methodentext der GetElementCategory-Methode hinzu
Fügen Sie den folgenden Code als Text der GetElementCategory-Methode hinzu:
return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementTypeDescription( element.ElementClass);
Return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementTypeDescription(element.ElementClass)
Relevante Typen und Methoden: DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices und GetElementTypeDescription.
Im nächsten Schritt wird der Text der GetElementName-Methode hinzugefügt.
So fügen Sie den Methodentext der GetElementName-Methode hinzu
Fügen Sie den folgenden Code als Text der GetElementName-Methode hinzu:
return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementName( element, ElementNameStyle.FullyQualifiedName);
Return _sourceModel.DatabaseSchemaProvider.UserInteractionServices.GetElementName(element, ElementNameStyle.FullyQualifiedName)
Relevante Typen und Methoden: DataSchemaModel, DatabaseSchemaProvider, UserInteractionServices, GetElementName und ElementNameStyle.
Speichern Sie die Änderungen an der Klasse. Im nächsten Schritt wird die Klassenbibliothek erstellt.
So signieren und erstellen Sie die Assembly
Klicken Sie im Menü Projekt auf Eigenschaften von MyDeploymentContributor.
Klicken Sie auf die Registerkarte Signierung.
Klicken Sie auf Assembly signieren.
Klicken Sie im Feld Schlüsseldatei mit starkem Namen auswählen auf <Neu>.
Geben Sie im Dialogfeld Schlüssel für einen starken Namen erstellen unter Schlüsseldateiname den Namen MyRefKey ein.
(optional) Sie können für die Schlüsseldatei mit starkem Namen ein Kennwort angeben.
Klicken Sie auf OK.
Klicken Sie im Menü Datei auf Alle speichern.
Klicken Sie im Menü Erstellen auf Projektmappe erstellen.
Danach müssen Sie die Assembly installieren und registrieren, damit sie geladen wird, wenn Sie Datenbankprojekte bereitstellen.
Installieren eines Bereitstellungscontributors
Führen Sie zum Installieren eines Bereitstellungscontributors die folgenden Aufgaben aus:
Kopieren der Assembly und der zugeordneten PDB-Datei in den Ordner "Extensions"
Erstellen einer Datei vom Typ "Extensions.xml", um den Bereitstellungscontributor zu registrieren, damit er bei der Bereitstellung von Datenbankprojekten geladen wird
So installieren Sie die Assembly "MyDeploymentContributor"
Erstellen Sie im Verzeichnis "%Programme%\Microsoft Visual Studio 10.0\VSTSDB\Extensions" den Ordner MyExtensions.
Kopieren Sie die signierte Assembly (MyDeploymentContributor.dll) und die zugeordnete PDB-Datei (MyDeploymentContributor.pdb) in den Ordner %Programme%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions.
Tipp
Es empfiehlt sich, die XML-Dateien nicht direkt in das Verzeichnis "%Programme%\Microsoft Visual Studio 10.0\VSTSDB\Extensions" zu kopieren. Wenn Sie stattdessen einen Unterordner verwenden, vermeiden Sie versehentliche Änderungen an den anderen Dateien, die mit Visual Studio Premium bereitgestellt werden.
Im nächsten Schritt muss die Assembly (eine Art Funktionserweiterung) registriert werden, damit sie in Visual Studio Premium angezeigt wird.
So registrieren Sie die Assembly "MyDeploymentContributor"
Klicken Sie im Menü Ansicht auf Weitere Fenster, und klicken Sie anschließend auf Befehlsfenster, um das Befehlsfenster zu öffnen.
Geben Sie im Befehlsfenster folgenden Code ein. Ersetzen Sie FilePath durch den Pfad und Dateinamen der kompilierten DLL-Datei. Schließen Sie Pfad und Dateiname in Anführungszeichen ein.
Tipp
Der Pfad der kompilierten DLL-Datei lautet standardmäßig Projektmappenpfad\bin\Debug oder Projektmappenpfad\bin\Release.
? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
? System.Reflection.Assembly.LoadFrom("FilePath").FullName
Drücken Sie die EINGABETASTE.
Kopieren Sie die resultierende Zeile in die Zwischenablage. Die Zeile sollte der folgenden entsprechen:
"MyDeploymentContributor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
Öffnen Sie einen Text-Editor, z. B. Editor.
Wichtig
Öffnen Sie den Editor unter Windows Vista und unter Microsoft Windows Server 2008 als Administrator, damit Sie die Datei im Ordner "Programme" speichern können.
Stellen Sie die folgenden Informationen bereit, und geben Sie dabei eigene Werte für Assemblyname, öffentliches Schlüsseltoken und Erweiterungstyp an:
<?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>
Diese XML-Datei dient zum Registrieren der Klasse, die von DeploymentPlanExecutor erbt.
Speichern Sie die Datei im Verzeichnis "%Programme%\Microsoft Visual Studio 10.0\VSTSDB\Extensions\MyExtensions" als "MyDeploymentContributor.extensions.xml".
Schließen Sie Visual Studio.
Im nächsten Schritt wird ein Datenbankprojekt bereitgestellt, um den Contributor zu testen.
Testen des Bereitstellungscontributors
Führen Sie zum Testen des Bereitstellungscontributors die folgenden Aufgaben aus:
Hinzufügen einer Eigenschaft zur bereitzustellenden DBPROJ-Datei
Bereitstellen des Datenbankprojekts mithilfe von MSBuild und Angeben des entsprechenden Parameters
Hinzufügen von Eigenschaften zur Datenbankprojektdatei (DBPROJ-Datei)
Wenn Sie diesen Bereitstellungscontributor mithilfe von MSBuild verwenden möchten, müssen Sie das Datenbankprojekt ändern, um Benutzern das Übergeben eines Parameters mithilfe von MSBuild zu ermöglichen. Um das Datenbankprojekt zu aktualisieren, öffnen Sie diese in einem Editor Ihrer Wahl, und fügen Sie der DBPROJ-Datei die folgenden Anweisungen zwischen dem letzten </ItemGroup>-Knoten in der Datei und dem letzten </Project>-Knoten hinzu:
<ItemGroup>
<DeploymentContributorArgument Include="GenerateUpdateReport=$(GenerateUpdateReport)" />
</ItemGroup>
Nach dem Aktualisieren der DBPROJ-Datei können Sie MSBuild verwenden, um die Parameter für Befehlszeilenbuilds zu übergeben.
Bereitstellen des Datenbankprojekts
So können Sie das Datenbankprojekt bereitstellen und einen Bereitstellungsbericht generieren
Öffnen Sie eine Visual Studio-Eingabeaufforderung. Klicken Sie im Startmenü auf Alle Programme, auf Microsoft Visual Studio 2010, auf Visual Studio Tools und anschließend auf Visual Studio-Eingabeaufforderung (2010).
Navigieren Sie an der Eingabeaufforderung zu dem Ordner, der das Datenbankprojekt enthält.
Geben Sie an der Eingabeaufforderung die folgende Befehlszeile ein:
MSBuild /t:Rebuild MyDatabaseProject.dbproj /p:OutDir=.\
Ersetzen Sie MyDatabaseProject durch den Namen des Datenbankprojekts, das Sie erstellen möchten. Wenn das Projekt seit der letzten Erstellung geändert wurde, können Sie anstelle von "/t:Rebuild" die Option "/t:Build" verwenden.
Geben Sie an der Eingabeaufforderung die folgende Befehlszeile ein:
MSBuild /t:Deploy MyDatabaseProject.dbproj /p:GenerateUpdateReport=true
Ersetzen Sie MyDatabaseProject durch den Namen des Datenbankprojekts, das Sie bereitstellen möchten.
Die angezeigte Ausgabe ähnelt dem folgenden Beispiel:
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
Öffnen Sie "MyTargetDatabase.summary.xml", und untersuchen Sie den Inhalt.
Die Datei ähnelt dem folgenden Beispiel, in dem eine neue Datenbankbereitstellung veranschaulicht wird:
<?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>
Tipp
Wenn Sie ein Datenbankprojekt bereitstellen, das mit der Zieldatenbank identisch ist, ist der daraufhin angezeigte Bericht nicht sonderlich aussagekräftig. Stellen Sie zum Erhalten aussagekräftigerer Ergebnisse entweder Änderungen an einer Datenbank oder eine neue Datenbank bereit.
Öffnen Sie MyTargetDatabase.details.xml, und untersuchen Sie den Inhalt.
Ein kurzer Abschnitt der Detaildatei gibt die Einträge und das Skript zum Erstellen des Schemas Sales, zum Ausgeben einer Meldung zum Erstellen einer Tabelle sowie zum Erstellen der Tabelle an:
<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>
Durch Analysieren des Bereitstellungsplans während der Ausführung können Berichte zu sämtlichen Informationen erstellt werden, die in der Bereitstellung enthalten sind. Darüber hinaus können weitere Aktionen auf der Grundlage der Schritte in diesem Plan ausgeführt werden.
Nächste Schritte
Sie können weitere Tools erstellen, um die XML-Ausgabedateien zu verarbeiten. Dies ist lediglich ein einzelnes Beispiel für einen DeploymentPlanExecutor. Sie können auch einen DeploymentPlanModifier erstellen, um einen Bereitstellungsplan vor dessen Ausführung zu ändern.
Siehe auch
Konzepte
Erweitern der Datenbankfunktionen von Visual Studio
Weitere Ressourcen
Anpassen von Datenbankbuild und -bereitstellung mithilfe von Build- und Bereitstellungsmitwirkenden