Differences between SqlPackage.exe and MsBuild SqlPublishTask - sql-server

I'm trying to generate an output dacpac file which I can then deploy to different environments. Until now I was deploying directly from msbuild using the target publish, something like:
msbuild dbproject.sqlproj /t:Build;Publish /p:SqlPublishProfilePath=test.publish.xml /p:UpdateDatabase=True /p:PublishScriptFileName=test.sql
The size of the ouput script generated (just for reference as UpdateDatabase is set to true) is 2.5MB.
My new approach is to just build the project, store the dacpac and then deploy using sqlpackage with action 'Publish'. This new method is reporting some warnings which were not reported by msbuild SqlPublishTask.
For reference I ran the next command:
sqlpackage.exe /action:script /outputpath:test.sql /sourcefile:dbproject.dacpac /pr:test.publish.xml
and the size of the output script is now 4.9MB.
The specific warnings reported are not the concern here, the concern is that the script is different, my question is what is the difference?
and more importantly which one would be the best/safest method to do the deploy?

Sqlpackage.exe is more detailed and includes more objects during the deployment, it drops the permissions to tables to avoid any modification during the modification of the objects and then it proceeds to create or modify the them.
The difference is that ALL the objects are included in the script of sqlpackage, independently on whether they are different or not from the target database.
Although the warnings given were not a concern initially, using the sqlpackage method I discovered that some store procedure were not in the solution, only in the database. These 'orphan' sp were referencing tables being deployed, which is giving a warning stating that a change in the table may break the sp.

Related

SQL Server Database Project

I want to use database project for script deployment in Azure SQL Server, I don't want to import full database. I just want to use database project for delta script. I added a project and included one script file with none as build action that contains create table statement , I am publishing the project, It's completing successfully but create statement is not executing. What is wrong here? Is there any other way to do this?
TLDR: Set your build action to "Post Deployment Script".
Longer:
What happens in SSDT is that all the files that have a build action of "Build" are built into a model of what the database should look like. When the deploy happens that model is compared to the target database and if there are any changes, a change script it generated and then optionally deployed.
If you have any file marked pre or post deployment script then they are either prepended or appended to the change script and will be run as part of the deployment.
If you have any files with a build action of "None" then SSDT ignores them, you could put anything in there, even an ascii picture of a donkey and the project will still build and deploy (obviously your ascii donkey won't get deployed anywhere).
If you just want to use SSDT to do your deployments you can just set the build action to pre or post deploy and it will be included. This is pretty odd though, either don't use SSDT or use SSDT and put the model of your entire database in there.
Personally, I would use SSDT properly and live the dream.
Ed

Database Project Over Multiple Environments?

How can you have environment specific table values in your database project and make sure that they only deploy to the environment you are deploying to with Release Management? We have been using Release Management for some time now, but only for .NET code. We are somewhat new to the DACPAC realm, but have found it easy to set up and use via release management. However, now we want to extend this capability to a table that has configuration variables per environment. How do we make this part of our database project and make sure that each environment has its own unique version of data?
Use SSDT for publishing the database schema and reference data; don't use it to manage environment settings.
Personally, I would (and have) run a secondary script post-deployment that configured environment-specific values. This is no different than putting the correct values in the web.config file of a web application post-deployment. It's something you manage within your deployment tool.
Ignoring the release management part to the question (because it depends what mode you use and whether you store configuration variables in RM etc) you can certainly pass in environment specific values into your dacpac execution (for use in 'postdeploy' data scripts) using sqlcmd variables defined in a tokenised publish file.
Broadly the process is:
Use standard sqlcmdvar syntax in your post deploy script e.g insert into table values '$(my_env_var)'
update the database project properties (sqlcmd tab) to include your new variable which ensures your dacpac expects a value when executed
Generate a publish.xml file (which should now include a node)
create a publish.release.xml file which contains transform instructions to update the value of your node to introduce a token e.g. ##my_env_var##
update your database project file(.sqlproj) to include instructions to transform publish.xml on build using the contents of publish.release.xml
Its quite long winded but what you get out of the above is a dacapac + tokenised publish file in your build output ready to be detokenised and executed by your deployment process..be that RM or any other tool.

How I know any particular one command is failed while deploying/publishing data in Database?

I have created database project in visual studio 2013. Project build successfully . In this project I have inserted some test data in post deployment. If any data failed to insert then how can know the one of script is failed at particular location.
Actually I want to rollback all the thing if any command is failed from script file itself. Since SQL Server 2012 is not supporting rollback from pre/post deployment script.
The result window will give you the line and details of any error, it is a bit annoying as it will sometimes show the text of the beginning of the script but the error line number will be correct.
General things you should do is to make sure your insert scripts are re-runnable and then if you really can't see the error you can run the script yourself to debug it.
I would really recommend using MERGE statements to do the inserts :)
I also generally recommend using sqlpackage.exe to push to local Deb instances rather than the vs publish, see:
https://the.agilesql.club/blog/Ed-Elliott/Visual-Studio-SSDT-Publish-My-Personal-Best-Practices
Ed

dacpac - CLR assembly reference path issue

Following is the exact scenario in my database project, where I am creating dacpac to deploy databases on target SQL instance:
the database project is having a reference of CLR assembly.
TFS build server is used to build the project
dacpac is getting created during TFS build process
– when i try to run sqlpackage.exe to deploy the dacpac (generated in TFS build process) in my environment, I get an error saying –
*** No file was supplied for reference XXXX.XXXX.XXXX.dll; deployment might fail. When C:\Temp\Dacpac_testing\XXX.XXXXX.XXXX.dacpac was
created, the original referenced file was located
C:\BUILDS\1\XXXX\XXXX\SRC\XXXXXXXX\ASSEMBLIES\XXXX.XXXX.XXXX.dll
How can I create a dacpac to reference the path of CLR assembly on deployment environment (and not the one that was used at the time of building dacpac)
Any help on this will be much appreciated.
Sorry I only picked on this thread now, but I had a similar issue.
Open the references in the Sql Server project, go to the dll that you are referencing right click and select properties.
Change the following settings:
Generate Sql Script: True
Model Aware: True
Select the relevant Permission set as required by the clr code.
I was able to solve this issue by including all the files in the bin/output folder that is built by the SSDT project on the machine that is deploying the dacpac. This folder includes all the referenced DLLs and DAPACs. I also included the publish.xml file and some sample SQLPackage cmd files in the build output to make it easy to deploy.
I found the answer from a post by Richard Gavel in the SQL Server Data Tools forum.
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/aba60b70-396f-4624-890c-015c1f2d68f7/dacpac-dependencies-for-sqlpackageexe?forum=ssdt
I don't know if this helps but I was having trouble running SqlPackage /Action:Script between my compiled DACPAC and an extracted DACPAC and got a similar error (An error occurred while adding references). I resolved it by copying all the DACPACS from the \bin\debug directory of my DACPAC (it has about references to 15 other database projects plus master and msdb). After that, it worked. So it seems that in looking for references, it will check the directory first (I don't know if it was looking specifically at the current directory or the one the root DACPAC was in because those were one and the same).

Database project - running Build Action=None SQL scripts

When I choose "Publish..." from a Visual Studio database project, it looks like, among other things, it runs the project's scripts on the database, but only the ones that have Build Action set to "Build". In other words, Build Action "None" scripts don't get run on the database as part of a Publish.
I have a database project but I do not have all the database's items in that project. Can I still keep scripts (for example, for stored procedures) in my project and run them on the database? How?
If I set them to "Build", I get build errors, because the items they depend on are not in the project. If I set them to "None", they don't run on the database at all. Is there a way to make them run on the database without needing their dependent items? If not, what is the best way to do this?
You could try setting the build action to none on the script, and then running the script from a post-deployment script.
There can only be one post-deployment script in each database project. You can add it by adding a new item and searching for post-deployment. Within the script, you use the command syntax to execute scripts.
http://www.mssqltips.com/sqlservertutorial/3006/working-with-pre-and-post-deployment-scripts/
It seems like there is no way to do what I am looking for; that Database projects were meant to have all the dependencies resolved.

Resources