Question

Visual Studio database edition comes with a tool, vsdbcmd.exe, that should allow someone to deploy a .dbschema file (which is generated by the database project on build) to a database. It does this by first building the script, then executing it:

vsdbcmd.exe /a:Deploy /cs:"Data Source=(local);Integrated Security=True;Pooling=False" /dsp:Sql /dd /model:"..\Database.dbschema" /p:TargetDatabase=TargetDB /manifest:"..\Database.deploymanifest"

I would expect that it can deploy the script to a different database server without problems. However, the complete path to the actual .mdf file is encoded in the script, along with some other references to the original databse. Either there isn't an option to control this, or I can't find it.

Is anyone using this? How do you deploy? Should I have used a different kind of database project (I remember having the choice way back when between "Database project" and "Server project", but I don't know whether that matters)?

EDIT

I can override the .sqlcmdvars just fine, but this does not solve the problem. This is an extract from the generated .sql file using a command like above:

GO
:setvar DatabaseName "TargetDB"
:setvar DefaultDataPath "C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\"

So there is the "targetdb" target database gets recorded correctly. But, a few lines further:

CREATE DATABASE [$(DatabaseName)]
ON 
PRIMARY(NAME = [Original], FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\Original.mdf', SIZE = 3072 KB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024 KB)
LOG ON (NAME = [Original_log], FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\Original_log.ldf', SIZE = 1024 KB, MAXSIZE = 2097152 MB, FILEGROWTH = 10 %)

where Original.mdf is the name of the original database (i.e. the db where we deploy during development, and that is set in the project properties of the database project). This is where the deployment fails, either because that exact path may be different on the target machine, or on my machine because that db already exists.

These values just seem hardcoded in the generated script.

Was it helpful?

Solution

This can be (is) caused when doing a Database Schema Synchronization -> Database Project. (My environment is VS2010 Enterprise RTM).

The generated ALTER DATABASE statements are generated to mirror the source database without taking any substitution values into account (it will also include initial database sizes, etc). The problem does not appear on an Initial Database Import.

Edit the files found under...

Schema Objects\Database Level Objects\Storage\Files

...and fix them to contain the correct $(DefaultDataPath)$(DatabaseName).mdf/$(DefaultLogPath)$(DatabaseName)_log.ldf values -- or other -- as appropriate. (Now mark them as "Skip" in your Schema Compare :-P)

With the above "correction" keeping the values external will once again work and is the preferred method of managing such properties.

Happy coding.

OTHER TIPS

Based on your edit, perhaps this is helpful. https://blogs.msdn.com/gertd/Default.aspx?p=7

Adding variables

So far we have been looking at how things work, now it is time to add some new variables and put them to work. One place where variables come in handy is in the post deployment file that defines files: storage.sql. Variables will allow use to make the location environment dependent.

Inside the storage file you will find something like this:

IF NOT EXISTS(SELECT 1 FROM dbo.sysfiles WHERE name = 'fgdb_data') BEGIN ALTER DATABASE [$(databasename)] ADD FILE ( NAME = N'fgdb_data', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\fgdb_data.ndf', MAXSIZE = 100MB, FILEGROWTH = 10MB ) TO FILEGROUP [TABLES] END

We could parameterize this so the drive and directory get abstracted through a variable to:

:setvar drive "C:" :setvar directory "Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA"

IF NOT EXISTS(SELECT 1 FROM dbo.sysfiles WHERE name = 'fgdb_data') BEGIN ALTER DATABASE [$(databasename)] ADD FILE ( NAME = N'fgdb_data', FILENAME = N'$(drive)\$(directory)\fgdb_data.ndf', MAXSIZE = 100MB, FILEGROWTH = 10MB ) TO FILEGROUP [TABLES] END

Now that we have parameterized the script, next we want to make the variables part of the project file, so we have them defined in a single place instead of scattered around in the code at various places through :setvar statements.

Sorry I am just starting to learn the GDR myself but I'll need the answer to this to

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top