共用方式為


逐步解說:使用 Visual Studio Automation 模型修改資料庫專案

更新:2007 年 11 月

藉由使用 Visual Studio 中的擴充性支援,您可以程式設計方式修改「資料庫專案」(Database Project)。Visual Studio Team System Database 版中的資料庫專案支援 Visual Studio Automation 模型 (也稱為設計階段擴充性或 DTE) 的方式,與 Visual C# 和 Visual Basic 專案的支援方式一致。如需此模型的詳細資訊,請參閱擴充 Visual Studio 環境。在本逐步解說中,您將會建立使用 Automation 模型的 Visual Studio 巨集完成兩項工作:

  • 切換資料庫專案中所有觸發程序的建置動作。如果觸發程序設定為「組建」,巨集就會將其變更為「不在組建中」。如果觸發程序設定為「不在組建中」,巨集就會將其變更為「組建」。

  • 將目錄中的所有指令碼檔加入到資料庫專案的資料夾中。如果資料夾不存在,則會加以建立。只會加入具有特定副檔名的指令碼檔。

您也可以在使用 Visual C# 或 Visual Basic 撰寫的 Visual Studio 增益集中執行這些工作。為了簡化,本逐步解說會使用巨集。

在下列程序中,您將會:

  • 建立依物件型別組織的資料庫專案,並匯入 AdventureWorks 資料庫結構描述。

  • 啟動 [巨集總管],並建立包含巨集和支援程式碼的模組。

  • 建立巨集以切換開啟方案的資料庫專案中所有觸發程序的建置動作。

  • 建立巨集和支援程式碼,以加入指令碼至資料庫專案中。

  • 從 [命令視窗] 執行 ToggleTriggers 巨集。

  • 從 [巨集總管] 執行 AddScriptsInDirectory 巨集。

必要條件

若要完成這個逐步解說,您必須安裝 Database 版。這個逐步解說假設您已經將 AdventureWorks 範例資料庫的複本安裝在執行 Microsoft SQL Server 2005 的資料庫伺服器上。您可以使用依物件型別組織的任何其他資料庫專案做為替代。在您可以存取的目錄中必須有一或多個副檔名為 .sql 的檔案。

若要建立資料庫專案

  1. 如果尚未啟動 Visual Studio,請啟動該程式。

  2. 在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。

    [新增專案] 對話方塊隨即出現。

  3. 在 [專案類型] 清單中,展開 [資料庫專案] 節點,然後按一下 [Microsoft SQL Server]。

  4. 按一下 [範本] 清單中的 [SQL Server 2000]。

  5. 在 [名稱] 中,輸入 MyAdvWorks,並接受 [位置] 和 [方案名稱] 的預設值。

  6. 選取 [為方案建立目錄] 核取方塊 (若預設情況下尚未選取),然後按一下 [確定]。

    即會建立包含 MyAdvWorks 這個空白資料庫專案的方案。

    接下來,您將會啟動 [匯入資料庫結構描述] 程序,您將會在此程序中指定連接至「來源」(Source) 資料庫的連接字串。

若要從現有的 AdventureWorks 資料庫匯入資料庫結構描述

  1. 按一下 [檢視] 功能表上的 [結構描述檢視]。

    [結構描述檢視] 隨即出現 (如果尚未出現)。

  2. 按一下 [結構描述檢視] 中的 MyAdvWorks。

  3. 按一下 [專案] 功能表上的 [匯入資料庫結構描述]。

    注意事項:

    您也可以用滑鼠右鍵按一下 [MyAdvWorks],然後按一下 [匯入資料庫結構描述]。

    [匯入資料庫精靈] 隨即出現。

  4. 在 [來源資料庫連接] 清單中,按一下對應到現有 AdventureWorks 資料庫的連接。如果您尚未連接到此資料庫,必須先建立此資料庫的連接。如需詳細資訊,請參閱 HOW TO:建立資料庫連接。

  5. 按一下 [完成]。

    當匯入結構描述時,對應到資料庫物件的專案項目會出現在 [方案總管] 的資料庫專案底下。[結構描述檢視] 會顯示此資料庫專案中所定義的物件。

若要啟動巨集總管和建立模組

  1. 在 [檢視] 功能表上,指向 [其他視窗],然後按一下 [巨集總管]。

    [巨集總管] 隨即出現。

  2. 在 [巨集總管] 中,以滑鼠右鍵按一下 [MyMacros] 節點,然後按一下 [新增模組]。

    [加入模組] 對話方塊隨即出現。

  3. 在 [名稱] 中,輸入 BuildActionExample。

  4. 按一下 [加入]。

  5. 在 [巨集總管] 中,以滑鼠右鍵按一下 [MyMacros] 節點,然後按一下 [新增模組]。

    [加入模組] 對話方塊隨即出現。

  6. 在 [名稱] 中,輸入 ImportScriptsExample。

  7. 按一下 [加入]。

    接下來,您建立的巨集會切換指定資料庫中所有「資料操作語言」(Data Manipulation Language,DML) 觸發程序的建置動作。

建立 ToggleTriggers 巨集

ToggleTriggers 巨集採用一個選擇性參數,代表包含要更新觸發程序的資料庫專案的名稱。如果沒有指定專案名稱,巨集會提示您提供名稱。您可以修改巨集,改為用來識別方案中每個專案的類型,並更新所有資料庫專案。不過,這個方法並不在本逐步解說的討論範圍內。

若要建立 ToggleTriggers 巨集

  1. 在 [巨集總管] 中,以滑鼠右鍵按一下 [BuildActionExample] 模組,然後按一下 [編輯]。

    [Microsoft Visual Studio Macros] 視窗隨即出現。這個視窗中會顯示 BuildActionExample 模組的內容。

  2. 以下列 VBScript 程式碼取代模組內容:

    Imports System
    Imports System.ComponentModel
    Imports EnvDTE
    Imports EnvDTE80
    Imports System.Diagnostics
    
    Public Module BuildActionExample
    
        ' Macro to toggle the BuildAction for all DML triggers
        ' in a database project.
        ' Before running this macro, you must:
        ' 1) Ensure that a solution file is open and saved to disk.
        ' 2) Pass in the name of a database project contained in the
        '    open solution in the dbProjName parameter. 
        Sub ToggleTriggers(Optional ByVal dbProjName As String = "")
            Dim project As Project
    
            ' if the database project name was not passed in, prompt the user for it.
            If (String.IsNullOrEmpty(dbProjName)) Then
                dbProjName = InputBox("Type the database project name.")
                If (String.IsNullOrEmpty(dbProjName)) Then
                    Return
                End If
            End If
    
            ' Loop through each project until we find the one we want
            For Each project In DTE.Solution
                Dim projectItem As EnvDTE.ProjectItem
                'Look for a project whose name matches the parameter
                If (dbProjName.Equals(project.Name)) Then
                    'Then loop through the project items, looking for
                    'the Schema Objects folder.
                    For Each projectItem In project.ProjectItems()
                        If (projectItem.Name = "Schema Objects") Then
                            ' loop through the subfolders and list the files, looking for the Tables sub-folder
                            Dim subItem As EnvDTE.ProjectItem
                            For Each subItem In projectItem.ProjectItems()
                                If (subItem.Name = "Tables") Then
                                    ' loop through looking for the Triggers subfolder
                                    Dim subsubItem As EnvDTE.ProjectItem
                                    For Each subsubItem In subItem.ProjectItems()
                                        If (subsubItem.Name = "Triggers") Then
                                            ' okay, we're in the right folder, now set the build actions
                                            Dim triggerItem As EnvDTE.ProjectItem
                                            For Each triggerItem In subsubItem.ProjectItems()
                                                'MsgBox(" trigger: " + triggerItem.Name)
                                                Dim buildAction As EnvDTE.Property
                                                buildAction = triggerItem.Properties.Item("DBProjectBuildAction")
    
                                                ' here we toggle the build action. If it was NotInBuild(0),
                                                ' we set it to Build(1). If it was Build(1), then we set it
                                                ' to NotInBuild(0).
                                                If (buildAction.Value = 0) Then
                                                    buildAction.Value = 1
                                                ElseIf (buildAction.Value = 1) Then
                                                    buildAction.Value = 0
                                                End If
                                            Next
                                        End If
                                    Next
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        End Sub
    End Module
    

    巨集會逐一查看方案內容,直到找到資料庫專案名稱與您指定的名稱相符。巨集識別出該專案後,會逐一查看專案項目,尋找 [方案項目] 資料夾。在 [方案項目] 資料夾中,巨集會尋找 [資料表] 資料夾,並在其中尋找 [觸發程序] 資料夾。接著,巨集會擷取每個觸發程序的 [DBProjectBuildAction] 屬性值。如果值是 1 (組建),就切換為 0 (不在組建中)。同樣的,如果值是 0,就切換為 1。雖然 [屬性] 視窗中的屬性名稱是 [建置動作],但實際上的屬性名稱是 [DBProjectBuildAction]。

  3. 在巨集視窗中,開啟 [檔案] 功能表,再按一下 [儲存 MyMacros]。

    接下來,您建立的巨集會將目錄中的指令碼檔加入到指定資料庫專案中。

建立 AddScriptsInDirectory 巨集

AddScriptsInDirectory 巨集採用 3 個參數:要加入指令碼檔的資料庫專案的名稱、要加入指令碼檔的資料庫專案資料夾的名稱,以及包含巨集要匯入指令碼檔的路徑。如果執行巨集時沒有指定這些參數,就會提示您提供參數。如果沒有指定專案資料夾名稱做為提示的回應,檔案就會加入到 [指令碼] 資料夾中。

這個巨集比先前的巨集來得複雜。為了簡化,您可以藉由建立下列兩個函式和兩個副程式來建置 AddScriptsInDirectory 巨集:

  • Function IsFileIncluded 這個函式會在要視為指令碼檔並要加入到資料庫專案的檔案的副檔名清單中,驗證是否有指定檔案名稱的副檔名。

  • Function GetOutputWindowPane 這個函式會傳回輸出視窗,好回報進度訊息。

  • Sub AddScriptsInDirectory2 這個副程式會採用專案資料夾和路徑,並加入所有副檔名符合指令碼副檔名清單的檔案。

  • Sub AddScriptsInDirectory 這個巨集的進入常式,這個副程式會處理傳入的參數、執行驗證,並且會建立目的資料夾或者是當資料庫專案中已經存在資料夾時負責找到該資料夾。接著副程式會呼叫 AddScriptsInDirectory2 以將檔案加入至該資料夾。

若要建立 AddScriptsInDirectory 巨集

  1. 在 [巨集總管] 中,以滑鼠右鍵按一下 [ImportScriptsExample] 模組,然後按一下 [編輯]。

    [Microsoft Visual Studio Macros] 視窗隨即出現。這個視窗中會顯示 ImportScriptsExample 模組的內容。

  2. 以下列 VBScript 程式碼取代模組內容:

    Imports System
    Imports EnvDTE
    Imports EnvDTE80
    Imports System.Diagnostics
    
    Public Module ImportScriptsExample
        ' A list of folder names, file names, and extensions that we want to add
        '  to the solution.
        Dim outputWindowPaneTitle As String = "Add scripts to a project folder report"
        Dim includedExtensions As New System.Collections.Specialized.StringCollection
    
        ' Function to filter out folder names, file names, and extensions that we do not 
        '  want to add to the solution.
        Function IsFileIncluded(ByVal filePath As String) As Boolean
            Dim extension As String
            Dim fileName As String
    
            extension = System.IO.Path.GetExtension(filePath)
            extension = extension.ToLower()
    
            fileName = System.IO.Path.GetFileName(filePath)
            fileName = fileName.ToLower()
    
            If (includedExtensions.Contains(extension)) Then
                Return True
            Else
                If (includedExtensions.Contains(fileName)) Then
                    Return True
                Else
                    Return False
                End If
            End If
        End Function
    
        ' This function retrieves the output window pane
        Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
            Dim window As Window
            Dim outputWindow As OutputWindow
            Dim outputWindowPane As OutputWindowPane
    
            window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
            If show Then window.Visible = True
            outputWindow = window.Object
            Try
                outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
            Catch e As System.Exception
                outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
            End Try
            outputWindowPane.Activate()
            Return outputWindowPane
        End Function
    
        ' Given a folder within the solution and a folder on disk, add all files whose extensions
        ' are on a list of "good" extensions to the folder in the solution.
        Sub AddScriptsInDirectory2(ByVal newScriptFolder As ProjectItem, ByVal startFolder As String)
            Dim files As String()
            Dim file As String
            Dim folder As String
    
            ' get a list of files in the specified folder
            files = System.IO.Directory.GetFiles(startFolder)
    
            ' get the output window pane so we can report status
            Dim outputWindowPane As EnvDTE.OutputWindowPane
            outputWindowPane = GetOutputWindowPane(outputWindowPaneTitle, True)
    
            ' Examine all the files within the folder.
            For Each file In files
                ' if this file's extension is one we want to include...
                If (IsFileIncluded(file)) Then
                    ' try to add it to the folder
                    Dim projItem As ProjectItem
                    Try
                        projItem = newScriptFolder.ProjectItems().AddFromFile(file)
                        outputWindowPane.OutputString("The item """ + file + """ was added" + vbLf)
    
                        If (Not (projItem Is Nothing)) Then
                            If (Not (projItem.Document Is Nothing)) Then
                                projItem.Document.Close(vsSaveChanges.vsSaveChangesNo)
                            End If
                        End If
                    Catch
                        ' if an error occurs, report the failure
                        outputWindowPane.OutputString("The item """ + file + """may have not been added to the solution." + vbLf)
                    End Try
                End If
            Next
        End Sub
    
        ' creates a new subfolder within the Scripts folder in the specified database project
        ' then adds all files in the specified path to the newly created scripts sub-folder.
        Sub AddScriptsInDirectory(Optional ByVal dbProjName As String = "", Optional ByVal scriptFolderName As String = "", Optional ByVal startFolder As String = "")
            If (String.IsNullOrEmpty(dbProjName)) Then
                dbProjName = InputBox("Type the name of the database project to which you want the scripts to be imported.")
                If (String.IsNullOrEmpty(dbProjName)) Then
                    Return
                End If
            End If
    
            If (String.IsNullOrEmpty(scriptFolderName)) Then
                scriptFolderName = InputBox("Type the script folder name.")
                If (String.IsNullOrEmpty(scriptFolderName)) Then
                    scriptFolderName = "Scripts"
                End If
            End If
    
            If (String.IsNullOrEmpty(startFolder)) Then
                startFolder = InputBox("Type the folder path to import.")
                If (String.IsNullOrEmpty(startFolder)) Then
                    Return
                End If
            End If
    
            If (System.IO.Directory.Exists(startFolder) = False) Then
                MsgBox("The specified folder could not be found.")
                Return
            End If
    
            GetOutputWindowPane(outputWindowPaneTitle, True).Clear()
    
            If System.IO.Directory.Exists(startFolder) = False Then
                Dim outputWindowPane As EnvDTE.OutputWindowPane
                outputWindowPane = GetOutputWindowPane(outputWindowPaneTitle, True)
                outputWindowPane.OutputString("The path entered could not be found" + vbLf)
                Exit Sub
            End If
    
            includedExtensions = New System.Collections.Specialized.StringCollection
            ' If you do not want a file with a particular extension or name
            '  to be added, then add that extension or name to this list:
            includedExtensions.Add(".sql")
            includedExtensions.Add(".tsql")
    
            Dim newScriptFolder As ProjectItem
            Dim project As Project
    
            ' now check to see if the desired folder in the project already exists
            For Each project In DTE.Solution
                Dim projectItem As EnvDTE.ProjectItem
    
                If (dbProjName.Equals(project.Name)) Then
                    Dim found As Boolean
                    found = False
                    For Each projectItem In project.ProjectItems()
                        If (scriptFolderName.Equals(projectItem.Name)) Then
                            ' the desired folder already exists, save the projectItem that corresponds
                            ' to the folder.
                            found = True
                            newScriptFolder = projectItem
                        End If
                    Next
    
                    ' if the folder does not exist within the project, create it.
                    If (Not found) Then
                        ' the folder does not already exist, so create it
                        newScriptFolder = project.ProjectItems().AddFolder(scriptFolderName, EnvDTE.Constants.vsProjectItemKindPhysicalFolder)
                    End If
                End If
            Next
    
            ' now add the scripts in the folder to the project folder
            AddScriptsInDirectory2(newScriptFolder, startFolder)
        End Sub
    End Module
    
  3. 在巨集視窗中,開啟 [檔案] 功能表,再按一下 [儲存 MyMacros]。

  4. 在 [檔案] 功能表上,按一下 [關閉並返回]。

    接下來,您將執行巨集以示範結果。

執行 ToggleTriggers 巨集

如果您不是以本逐步解說所建立的方案來執行巨集,則必須指定方案中包含的資料庫專案名稱而不是 MyAdvWorks。

若要從命令視窗執行 ToggleTriggers 巨集

  1. 在 [方案總管] 中,展開 [MyAdvWorks] 資料庫專案。

  2. 展開 [結構描述物件] 資料夾。

  3. 展開 [資料表] 資料夾。

  4. 展開 [觸發程序] 資料夾。

  5. 在 [方案總管] 中,以滑鼠右鍵按一下任何觸發程序,然後按一下 [屬性]。

    注意您所選觸發程序的 [建置動作] 屬性值。

  6. 在 [檢視] 功能表上,指向 [其他視窗],然後按一下 [命令視窗]。

    [命令視窗] 隨即出現。

  7. 在 [命令] 視窗中輸入下列:

    Macros.MyMacros.BuildActionExample.ToggleTriggers MyAdvWorks
    

    MyAdvWorks 是將要切換其觸發程序 [建置動作] 屬性的資料庫專案的名稱。

  8. 等候巨集完成。

  9. 巨集執行完成時,檢視步驟 5 的觸發程序屬性。

    [建置動作] 屬性值會是您執行巨集前屬性值的相反值。

    再次執行巨集即可還原 [建置動作] 屬性值為原始狀態。

    接下來,從 [巨集總管] 執行 AddScriptsInDirectory 巨集。

執行 AddScriptsInDirectory 巨集

如果您不是以本逐步解說所建立的方案來執行巨集,則必須指定方案中包含的資料庫專案名稱而不是 MyAdvWorks。

若要從巨集總管執行 AddScriptsInDirectory 巨集

  1. 如果 [巨集總管] 並未開啟,請開啟 [檢視] 功能表,然後指向 [其他視窗],再按一下 [巨集總管]。

    [巨集總管] 隨即出現。

  2. 在 [巨集總管] 中,以滑鼠右鍵按一下 [AddScriptsInDirectory] (可能需要展開 ImportScriptsExample 模組以顯示巨集),然後按一下 [執行]。

    [Visual Studio Macros] 對話方塊隨即出現,提示您「請輸入要匯入指令碼的資料庫專案名稱」。

  3. 輸入 MyAdvWorks,然後按一下 [確定]。

    [Visual Studio Macros] 對話方塊再次出現,提示您「請輸入指令碼資料夾名稱」。

  4. 按一下 [確定] 接受預設行為,即會將指令碼加入至 [指令碼] 資料夾。

    [Visual Studio Macros] 對話方塊再次出現,提示您「請輸入要匯入的資料夾路徑」。

  5. 輸入您指令碼檔所在的路徑,如本主題稍早的「必要條件」一節所註明。例如,如果指令碼在 C:\Temp,則輸入 C:\Temp,然後按一下 [確定]。

    巨集就會執行,將所有具 .sql 或 .tsql 副檔名的檔案加入到 MyAdvWorks 資料庫專案的 [指令碼] 資料夾中。

後續步驟

本逐步解說說明您對資料庫專案使用 Visual Studio Automation 模型時所能執行工作的小型範例。如果需要更多的彈性,您可以從 Visual Studio 增益集使用 Automation 模型。

請參閱

概念

專案擴充性簡介

Database Edition 的用語概觀

其他資源

Visual Studio Macros

建立增益集和精靈

參考 Automation 組件和 DTE2 物件