This blog post assumes you are using Visual Studio 2010. However, most of the information is relevant to Visual Studio Team System 2008 Database Edition GDR.
We get a lot of questions from customers for which we answer; use multiple projects (database and/or server). The following canonical examples represent the majority of what customers ask about
Define SQL instance level objects
For example, define Logins or Linked Servers.
Organize my code by SQL schema
For example, one project contains the objects bound to the HumanResources schema and another project contains the objects bound to the Sales schema.
Organize my code by SQL object type
For example, one project has all you tables and another project has all of your stored procedures.
Re-use the code implemented in one project in multiple database designs
For example you have some diagnostics functionality that you re-use in each of your database designs.
An important point is that in each of these cases the developer needs to use two part names when referring to objects declared in another project. A similar sounding but very different question is how to use multiple database projects when the developer wants to use three part names or four part names. That is the topic of another blog post. :)
The good news is that Data Dude makes it easy to implement the T-SQL code for the examples I’ve described above. If you implement C# or VB.NET code in Visual Studio you will find that the mechanics of setting up your solution are analogous to referencing assemblies. Customers seem to get confused with two areas
Before continuing I recommend that you first read this blog post: The pros and cons of Partial Projects and Database Project References for some important background information.
In this walk through I am going to break the AdventureWorks2008 database into projects representing each schema: HumanResources, Person, Production, etc. While it may seem pedantic to do a detailed walk through I find that many developers get stuck at one point or another. So it should be nice to have a relatively complex example that actually works in the end. If you would a walk through of putting together a new, simple database design I suggest you read this White Paper: Collaborative Development with Team System 2008 Database Edition.
These are the steps to the process we’re going to go through
There are several ways to do this
I think the first option is quicker than using Schema Compare so that’s what I’ll use. In future blog posts I’ll use the alternative methods so you can see how the different approaches compare. Throughout this process I’m going to make changes, resolve any errors in the solution, then make the next change. It’s an incremental “get clean, stay clean” sort of approach.
The key point to understand here is that we are only moving objects that do not refer to other schema into the individual projects. If an object depends on the HumanResources and Person schemas then we leave that object definition in the MyAdventureWorks2008 project. Foreign keys are the most common example of this sort of object definition.
As you can see from the following screenshot the import database process persists the .sql scripts into folders and files with the name of the schema. We want to move the objects in each of the schema that have no relationships with other schema into their respective project.
2. Move the objects bound to the HumanResources schema from the MyAdventureWorks2008 project into the HumanResources project
Now take a look at the long list of errors in the error list. Yikes, what have we done?
3. Let’s fix the unresolved references to Sql Types first.
4. Now let’s fix the errors caused by references to objects in other schema. We need to delete these scripts from the HumanResources project. Remove the following files
At this point all of the errors in the HumanResources project are resolved. We still have a few warnings, however.
5. Add another project to the solution named Diagnostics 6. Using Import Script import the following files from the MyAdventureWorks2008 project into the Diagnostics project. Then build the Diagnostics project. It should build successfully.
5. Add another project to the solution named Diagnostics
6. Using Import Script import the following files from the MyAdventureWorks2008 project into the Diagnostics project. Then build the Diagnostics project. It should build successfully.
7. Now add a Database Reference from the HumanResources project to the Diagnostics project. At this point you should not have any errors or warnings. Sweet!
8. Now add a Database References from the MyAdventureWorks2008 project to the HumanResources, SqlTypes and Diagnostics projects. You should see a bunch of errors. All of these are because all the objects that we moved to the other project are still defined in the MyAdventureWorks2008 project. Fixing this is basically a search and destroy effort. Look at the errors in the error list and remove each file from the MyAdventureWorks2008 project. When you have no errors you are done. :)
9. Repeat the previous steps for the remainder of the schemas.
When you move the objects bound to the [Sales] schema into the Sales project you will find that the function [dbo].[ufnLeadingZeros] is only used in one place – [Sales].[Customer]. Since it is only used in here I chose to move the function into the [Sales] schema. Arguably it belongs in a utility project with the rest of the functions defined in [dbo] so I can reuse the code in other database designs.
10. At this point I checked the solution into Source Code Control. That was a lot of work!
In order to actually deploy our database we need to configure a few settings in each project.
From Solution Explorer
Now attempt to deploy the solution – select Deploy Solution from the solution’s context menu in Solution Explorer. Notice that the Production project fails to deploy and displays the following error in the output window
c:\Projects\MyAdventureWorks\Production\sql\debug\Production.sql(328,0): Error SQL01268: .Net SqlClient Data Provider: Msg 1969, Level 16, State 1, Line 1 Default FILESTREAM filegroup is not available in database 'MyAdventureWorks2008'.
Unfortunately the Data Dude validation engine doesn’t catch this problem at design time. If it had we would have seen an error in the error list. To fix this we have some more code refactoring to do. We’re going to move the definition of the FILESTREAM filegroup and associated file from the MyAdventureWorks project to the Production project.
Now try to deploy again. It should succeed.
The diagram below describes the solution we have created. The primary purpose of the MyAdventureWorks2008 project is to define referential integrity between tables in the various schema and any application level views that do joins across tables in the various schema. In theory each of the projects other than the MyAdventureWorks project could be re-used in other database designs.