Search code examples
visual-studiomsbuildsql-server-data-tools

How to generate SSDT change script using MSBuild in CI environment?


Setup:
I have a Visual Studio 2019 .Net solution and there's an SSDT project in it.

Goal:
I need to generate an sql change script automatically on each CI build (TFS) for further including it to build artifacts for distribution.

I know there's sqlpackage.exe tool that can generate a change script, but it requires either an existing database connection or a *.dacpac file to compare against.

Is there a standard way to generate an sql change script automatically on each CI build?

UPDATE:

Example:

Version #1 of my sql project:

MyProject\Schema Objects\Schemas\dbo\Tables\MyTable.sql:

CREATE TABLE [dbo].[MyTable] (
    [Id] INT IDENTITY (1, 1) NOT NULL,
    [Name] VARCHAR (50) NOT NULL,
);

Version #2 of my sql project:

MyProject\Schema Objects\Schemas\dbo\Tables\MyTable.sql:

CREATE TABLE [dbo].[MyTable] (
    [Id] INT IDENTITY (1, 1) NOT NULL,
    [Name] VARCHAR (50) NOT NULL,
    [Description] VARCHAR (255) NOT NULL,
);

MyProject\Schema Objects\Schemas\dbo\Programmability\Stored Procedures\MyProcedure.sql

CREATE PROCEDURE [dbo].[MyProcedure]
BEGIN
...
...
END

Script that I can generate now:

CREATE DATABASE
...
...
CREATE TABLE MyTable
...
...
CREATE PROCEDURE MyProcedure
...
...

Script that I need (change script, containing only changes made relative to a previous version):

ALTER TABLE [dbo].[MyTable] 
ADD [Description] VARCHAR (255) NOT NULL

GO

ALTER PROCEDURE MyProcedure
...
...

GO

Solution

  • msbuild.exe $SqlProjPath /p:SqlPublishProfilePath=$SqlPublishProfilePath /p:UpdateDatabase=false /t:Build,Publish where the most important argument is UpdateDatabase and when it is false, it will just generate the script without publishing

    UPDATE (based on the comments): as far as I understand that connection to database is wanted to avoided. This is actually not recommended approach as normally you can't be 100% sure what exact version of database is currently on production (or whatever environment you are going to deploy to) as there could be million reasons why it drifted, most often because of some manual changes directly to database. That's why it is advised to compare to it. In any case, when working with SSDT you always need to have some database or dacpac to compare against. So, these are the options I can see:

    • Compare with real database
    • Extract dacpac from real database and compare against it
    • Checkout previous project version from source control, build project and compare current state with built dacpac
    • Save last deployed dacpac in version control and use it to compare. After deployment commit new version of dacpac

    The first option is most advisable and going down each approach getting worse.