연습: Visual Studio 자동화 모델을 사용하여 데이터베이스 프로젝트 수정
업데이트: 2007년 11월
Visual Studio의 확장성 지원을 사용하면 데이터베이스 프로젝트를 프로그래밍 방식으로 수정할 수 있습니다. Visual Studio Team System Database Edition의 데이터베이스 프로젝트는 Visual C# 및 Visual Basic 프로젝트와 일관된 방식으로 Visual Studio 자동화 모델(디자인 타임 확장성 또는 DTE라고도 함)을 지원합니다. 이 모델에 대한 자세한 내용은 Visual Studio 환경 확장을 참조하십시오. 이 연습에서는 자동화 모델을 사용하여 다음과 같은 두 가지 작업을 수행하는 Visual Studio 매크로를 만듭니다.
데이터베이스 프로젝트에 있는 모든 트리거의 빌드 작업을 전환합니다. 트리거가 "빌드"로 설정되어 있으면 매크로를 통해 "빌드에 없음"으로 변경됩니다. 트리거가 "빌드에 없음"으로 설정되어 있으면 매크로를 통해 "빌드"로 변경됩니다.
디렉터리에 있는 모든 스크립트 파일을 데이터베이스 프로젝트의 폴더에 추가합니다. 폴더가 없으면 새로 만들어집니다. 특정 확장명이 있는 스크립트 파일만 추가됩니다.
또한 Visual Basic 또는 Visual C#으로 작성된 Visual Studio 추가 기능에서도 이러한 작업을 수행할 수 있습니다. 이 연습에서는 편의상 매크로를 사용합니다.
아래 절차에서는 다음과 같은 작업을 수행합니다.
개체 형식별로 구성된 데이터베이스 프로젝트를 만들고 AdventureWorks 데이터베이스 스키마를 가져옵니다.
매크로 탐색기를 시작하고 모듈을 만들어 매크로 및 지원하는 코드를 포함합니다.
열려 있는 솔루션에 있는 데이터베이스 프로젝트의 모든 트리거에 대해 빌드 작업을 전환하는 매크로를 만듭니다.
데이터베이스 프로젝트에 스크립트를 추가하는 매크로 및 지원하는 코드를 만듭니다.
명령 창에서 ToggleTriggers 매크로를 실행합니다.
매크로 탐색기에서 AddScriptsInDirectory 매크로를 실행합니다.
사전 요구 사항
이 연습을 완료하려면 Database Edition이 설치되어 있어야 합니다. 이 연습에서는 Microsoft SQL Server 2005를 실행하는 데이터베이스 서버에 AdventureWorks 샘플 데이터베이스 복사본을 설치했다고 가정합니다. 개체 형식별로 구성된 다른 데이터베이스 프로젝트를 대신 사용할 수도 있습니다. 또한 액세스 권한이 있는 디렉터리에 확장명이 .sql인 파일이 하나 이상 있어야 합니다.
데이터베이스 프로젝트를 만들려면
Visual Studio를 시작합니다(아직 시작하지 않은 경우).
파일 메뉴에서 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.
새 프로젝트 대화 상자가 나타납니다.
프로젝트 형식 목록에서 데이터베이스 프로젝트 노드를 확장하고 Microsoft SQL Server를 클릭합니다.
템플릿 목록에서 SQL Server 2005를 클릭합니다.
이름에 MyAdvWorks를 입력하고 위치 및 솔루션 이름에 대해 기본값을 적용합니다.
기본적으로 선택되어 있지 않으면 솔루션용 디렉터리 만들기 확인란을 선택하고 확인을 클릭합니다.
빈 MyAdvWorks 데이터베이스 프로젝트가 포함된 솔루션이 생성됩니다.
다음에는 소스 데이터베이스에 대한 연결 문자열을 지정하는 데이터베이스 스키마 가져오기 프로세스를 시작합니다.
기존 AdventureWorks 데이터베이스에서 데이터베이스 스키마를 가져오려면
보기 메뉴에서 스키마 뷰를 클릭합니다.
스키마 뷰가 아직 표시되지 않은 경우 표시됩니다.
스키마 뷰에서 MyAdvWorks를 클릭합니다.
프로젝트 메뉴에서 데이터베이스 스키마 가져오기를 클릭합니다.
참고: MyAdvWorks를 마우스 오른쪽 단추로 클릭하고 데이터베이스 스키마 가져오기를 클릭할 수도 있습니다.
데이터베이스 가져오기 마법사가 나타납니다.
소스 데이터베이스연결 목록에서 기존 AdventureWorks 데이터베이스에 해당하는 연결을 클릭합니다. 아직 이 데이터베이스에 연결하지 않은 경우 먼저 연결을 만들어야 합니다. 자세한 내용은 방법: 데이터베이스 연결 만들기를 참조하십시오.
마침을 클릭합니다.
스키마를 가져올 때 데이터베이스에 있는 개체에 해당하는 프로젝트 항목이 솔루션 탐색기의 데이터베이스 프로젝트 아래에 나타납니다. 스키마 뷰에는 데이터베이스 프로젝트에 정의된 개체가 표시됩니다.
매크로 탐색기를 시작하여 모듈을 만들려면
보기 메뉴에서 다른 창을 가리킨 다음 매크로 탐색기를 클릭합니다.
매크로 탐색기가 나타납니다.
매크로 탐색기에서 MyMacros 노드를 마우스 오른쪽 단추로 클릭하고 새 모듈을 클릭합니다.
모듈 추가 대화 상자가 나타납니다.
이름에 BuildActionExample을 입력합니다.
추가를 클릭합니다.
매크로 탐색기에서 MyMacros 노드를 마우스 오른쪽 단추로 클릭하고 새 모듈을 클릭합니다.
모듈 추가 대화 상자가 나타납니다.
이름에 ImportScriptsExample을 입력합니다.
추가를 클릭합니다.
다음으로는 지정된 데이터베이스에 있는 모든 DML(데이터 조작 언어)의 빌드 작업을 전환하는 매크로를 만듭니다.
ToggleTriggers 매크로 만들기
ToggleTriggers 매크로는 업데이트할 트리거가 포함된 데이터베이스 프로젝트의 이름인 선택적 매개 변수 하나를 사용합니다. 프로젝트 이름을 지정하지 않으면 매크로에서 이를 지정하라는 메시지를 표시합니다. 솔루션의 각 프로젝트 형식을 대신 식별하고 모든 데이터베이스 프로젝트를 업데이트하도록 매크로를 수정할 수 있습니다. 그러나 이러한 접근 방식은 이 연습에서 다루지 않습니다.
ToggleTriggers 매크로를 만들려면
매크로 탐색기에서 BuildActionExample 모듈을 마우스 오른쪽 단추로 클릭하고 편집을 클릭합니다.
Microsoft Visual Studio Macros 창이 나타납니다. 이 창에는 BuildActionExample 모듈의 내용이 표시됩니다.
모듈의 내용을 다음 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입니다.
매크로 창에서 파일 메뉴를 열고 MyMacros 저장을 클릭합니다.
다음으로는 지정된 데이터베이스 프로젝트에 디렉터리의 스크립트 파일을 추가하는 매크로를 만듭니다.
AddScriptsInDirectory 매크로 만들기
AddScriptsInDirectory 매크로는 스크립트 파일을 추가할 데이터베이스 프로젝트의 이름, 스크립트를 추가할 데이터베이스 프로젝트의 폴더 이름 그리고 매크로에서 가져올 스크립트 파일이 포함된 경로의 세 가지 매개 변수를 사용합니다. 매크로를 실행할 때 이들 매개 변수를 지정하지 않으면 이를 지정하라는 메시지가 표시됩니다. 메시지가 나타날 때 프로젝트 폴더의 이름을 지정하지 않으면 파일이 스크립트 폴더에 추가됩니다.
이 매크로는 앞에서 살펴본 매크로보다 복잡합니다. 편의상 다음과 같은 두 개의 함수와 두 개의 서브루틴을 만들어 AddScriptsInDirectory 매크로를 빌드합니다.
Function IsFileIncluded 이 함수는 지정된 파일 이름의 확장명이 스크립트로 처리되어 데이터베이스 프로젝트에 추가되어야 하는 파일의 확장명 목록에 있는지 여부를 확인합니다.
Function GetOutputWindowPane 이 함수는 진행률 메시지를 보고할 수 있도록 출력 창을 반환합니다.
Sub AddScriptsInDirectory2 이 서브루틴은 프로젝트 폴더와 경로를 사용하고 확장명이 스크립트 확장명 목록의 항목과 일치하는 모든 파일을 추가합니다.
Sub AddScriptsInDirectory 이 매크로의 입력 루틴에 해당하는 이 서브루틴은 전달된 매개 변수를 처리하고, 유효성 검사를 수행하며, 대상 폴더를 만들거나 폴더가 이미 있는 경우 데이터베이스 프로젝트에서 이를 검색합니다. 그런 다음 이 서브루틴은 AddScriptsInDirectory2를 호출하여 해당 폴더에 파일을 추가합니다.
AddScriptsInDirectory 매크로를 만들려면
매크로 탐색기에서 ImportScriptsExample 모듈을 마우스 오른쪽 단추로 클릭하고 편집을 클릭합니다.
Microsoft Visual Studio Macros 창이 나타납니다. 이 창에는 ImportScriptsExample 모듈의 내용이 표시됩니다.
모듈의 내용을 다음 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
매크로 창에서 파일 메뉴를 열고 MyMacros 저장을 클릭합니다.
파일 메뉴에서 닫고 돌아가기를 클릭합니다.
다음으로 매크로를 실행하여 결과를 나타냅니다.
ToggleTriggers 매크로 실행
이 연습에서 만든 솔루션이 아닌 다른 솔루션에서 매크로를 실행하는 경우 MyAdvWorks 대신 해당 솔루션에 들어 있는 데이터베이스 프로젝트의 이름을 지정해야 합니다.
명령 창에서 ToggleTriggers 매크로를 실행하려면
솔루션 탐색기에서 MyAdvWorks 데이터베이스 프로젝트를 확장합니다.
스키마 개체 폴더를 확장합니다.
테이블 폴더를 확장합니다.
트리거 폴더를 확장합니다.
솔루션 탐색기에서 아무 트리거나 오른쪽 마우스 단추로 클릭하고 속성을 클릭합니다.
선택한 트리거의 빌드 작업 속성 값을 기록해 둡니다.
보기 메뉴에서 다른 창을 가리킨 다음 명령 창을 클릭합니다.
명령 창이 나타납니다.
명령 창에서 다음을 입력합니다.
Macros.MyMacros.BuildActionExample.ToggleTriggers MyAdvWorks
MyAdvWorks는 해당 트리거의 빌드 작업 속성이 전환될 데이터베이스 프로젝트의 이름입니다.
매크로가 완료될 때까지 기다립니다.
매크로가 실행을 마치면 5단계의 트리거에 대한 속성을 확인합니다.
빌드 작업 속성 값은 매크로를 실행하기 전의 값과 반대입니다.
매크로를 다시 실행하면 빌드 작업 속성 값을 원래 상태로 복원할 수 있습니다.
다음에는 매크로 탐색기에서 AddScriptsInDirectory 매크로를 실행합니다.
AddScriptsInDirectory 매크로 실행
이 연습에서 만든 솔루션이 아닌 다른 솔루션에서 매크로를 실행하는 경우 MyAdvWorks 대신 해당 솔루션에 들어 있는 데이터베이스 프로젝트의 이름을 지정해야 합니다.
매크로 탐색기에서 AddScriptsInDirectory 매크로를 실행하려면
매크로 탐색기가 열려 있지 않은 경우 보기 메뉴를 열고 다른 창을 가리킨 후 매크로 탐색기를 클릭합니다.
매크로 탐색기가 나타납니다.
매크로 탐색기에서 AddScriptsInDirectory(매크로를 표시하기 위해 ImportScriptsExample 모듈을 확장해야 할 수 있음)를 마우스 오른쪽 단추로 클릭하고 실행을 클릭합니다.
Visual Studio 매크로 대화 상자가 나타나면서 "Type the name of the database project to which you want the scripts to be imported."라는 메시지가 표시됩니다.
MyAdvWorks를 입력하고 확인을 클릭합니다.
Visual Studio 매크로 대화 상자가 다시 나타나면서 "Type the script folder name."이라는 메시지가 표시됩니다.
확인을 클릭하여 스크립트 폴더에 스크립트를 추가하는 기본 동작을 허용합니다.
Visual Studio 매크로 대화 상자가 다시 나타나면서 "Type the folder path to import."라는 메시지가 표시됩니다.
스크립트 파일이 있는 경로를 이 항목 앞부분의 필수 구성 요소 단원에 나와 있는 대로 입력합니다. 예를 들어 스크립트가 C:\Temp에 있는 경우 C:\Temp를 입력한 후 확인을 클릭합니다.
매크로는 확장명이 .sql 또는 .tsql인 파일이 MyAdvWorks 데이터베이스 프로젝트의 스크립트 폴더에 추가될 때까지 계속 실행됩니다.
다음 단계
이 연습에서는 데이터베이스 프로젝트에서 Visual Studio 자동화 모델을 사용하여 수행할 수 있는 간단한 샘플 작업을 살펴보았습니다. 보다 높은 융통성이 요구되는 경우에는 Visual Studio 추가 기능의 자동화 모델을 사용할 수도 있습니다.