Quantcast
Channel: Jamie Thomson : ssdt
Viewing all 54 articles
Browse latest View live

SQL Server Data Tools does support required variables

$
0
0

Over the past few years of using datadude (aka DBPro aka Visual Studio Database Projects) I have fallen prey to a peculiar little nuance – if you forget to supply a value for a sqlcmd variable then it will simply use a default and often that is not the desired behaviour. Hence why yesterday I submitted the following suggestion to http://connect.microsoft.com/sqlserver/feedback :

Specify sqlcmdvars properties as "required to be overridden”

In my current place of work I am responsible for maintaining our datadude projects and we have another team that is in charge of deployments. Hence, when we place new properties into the sqlcmdvars file I need to tell the deployment team what values to supply for that property per environment (dev, systest, uat, prod).
Unfortunately lack of communication/human error occasionally creeps in and, for whatever reason, no value gets supplied for some property at deployment time. If this is the case the default value as specified in the sqlcmdvars file gets used instead - invariably this will be the wrong value. I would like a mechanism within SSDT of preventing this from ever happening.

One simple way to prevent this would be to specify that a sqlcmdvars property is *required* to be overridden during the deployment. In other words, never use the default. if an override is not supplied at deployment time then the deployment should fail.
Note that this stipulation should only be in place when deployment occurs from the command-line - if deploying from Visual Studio the default should be allowed (simply because Visual Studio doesn't provide a way to specify anything other than the default value supplied in the sqlcmdvars file).

https://connect.microsoft.com/sqlserver/feedback/details/724366/ssdt-specify-sqlcmdvars-properties-as-required-to-be-overridden#details

It transpires that this requested feature is already available in the forthcoming SQL Server Data Tools (SSDT) as I shall now demonstrate. This screenshot shows the project properties of a SSDT project where we define the sqlcmd variables, I have defined a variable called $(Id_value):

image

In SSDT the nomenclature for deploying a project is “Publish”, a function that can be found by right-clicking on a project in Solution Explorer:

image

Selecting that brings up the Publish dialog.

image

Notice how the “Publish” button is greyed out – that it because I have not supplied a value for $(Id_value); supplying a value enables the Publish button and I can go ahead and publish my project. In other words, SSDT insists that I supply a value for that variable – exactly as I requested in my Connect submission.

The same is true if I use the command-line publishing tool sqlpackage.exe. The following command does essentially the same thing as the above depicted Publish dialog:

>sqlpackage.exe /TargetDatabaseName:MyDB /TargetServerName:".\RC0" /Action:Publish /SourceFile:"TestRequiredSqlCmdVars.dacpac"

Executing that gives me an error:

Publishing to database 'MyDB' on server '.\RC0'.
*** Missing values for the following SqlCmd variables:
'Id_value'.

Here’s a screenshot showing the same:

image

In order to supply a value for the variable from the command-line you need to use the /v: switch like so:

>sqlpackage.exe /TargetDatabaseName:MyDB /TargetServerName:".\RC0" /Action:Publish /SourceFile:"TestRequiredSqlCmdVars.dacpac" /v:Id_value=1

image

As you can see, publish was successful!

So there you go, using SSDT you’ll no longer be able to fall prey to the problem I highlighted at the top of this blog post. In a later blog post I’ll show how you CAN supply a default value if you want to and also how you can override for your local environment.

@jamiet


SSDT - What's in a name?

$
0
0

SQL Server Data Tools (SSDT) recently got released as part of SQL Server 2012 and depending on who you believe it can be described as either:

  • a suite of tools for building SQL Server database solutions

or

  • a suite of tools for building SQL Server database, Integration Services, Analysis Services & Reporting Services solutions

Certainly the SQL Server 2012 installer seems to think it is the latter because it describes SQL Server Data Tools as "the SQL server development environment, including the tool formerly named Business Intelligence Development Studio. Also installs the business intelligence tools and references to the web installers for database development tools" as you can see here:


Strange then that, seemingly, there is no consensus within Microsoft about what SSDT actually is. On yesterday's blog post First Release of SSDT Power Tools reader Simon Lampen asked the quite legitimate question:

I understand (rightly or wrongly) that SSDT is the replacement for BIDS for SQL 2012 and have just installed this. If this is the case can you please point me to how I can edit rdl and rdlc files from within Visual Studio 2010 and import MS Access reports.

To which came the following reply:

SSDT doesn't include any BIDs (sic) components. Following up with the appropriate team (Analysis Services, Reporting Services, Integration Services) via their forum or msdn page would be the best way to answer you questions about these kinds of services. 

That's from a Microsoft employee by the way. Simon is even more confused by this and replies with:

I have done some more digging and am more confused than ever. This documentation (and many others) : msdn.microsoft.com/.../ms156280.aspx expressly states that SSDT is where report editing tools are to be found

And on it goes....

You can see where Simon's confusion stems from. He has official documentation stating that SSDT includes all the stuff for building SSIS/SSAS/SSRS solutions (this is confirmed in the installer, remember) yet someone from Microsoft tells him "SSDT doesn't include any BIDs components".

I have been close to this for a long time (all the way through the CTPs) so I can kind of understand where the confusion stems from. To my understanding SSDT was originally the name of the database dev stuff but eventually that got expanded to include all of the dev tools - I guess not everyone in Microsoft got the memo.

Does this sound familiar? Have we not been down this road before? The database dev tools have had upteen names over the years (do any of datadude, TSData, VSTS for DB Pros, DBPro, VS2010 Database Projects sound familiar) and I was hoping that the SSDT moniker would put all confusion to bed - evidently its as complicated now as it has ever been.

Forgive me for whinging but putting meaningful, descriptive, accurate, well-defined and easily-communicated names onto a product doesn't seem like a difficult thing to do. I guess I'm mistaken!

Onwards and upwards...

@Jamiet

Update: There is evidence that they (Microsoft) are seeking to rectify this situation. In a blog comment Janet Yeilding whom, I assume, is on the SSDT team says:

We recognize that our messaging on what SSDT is has been confusing and even contradictory and we're working on getting a cleaner story in the future.

Northwind now available on SQL Azure

$
0
0

Two weeks ago I made available a copy of [AdventureWorks2012] on SQL Azure and published credentials so that anyone from the SQL community could connect up and experience SQL Azure, probably for the first time. One of the (somewhat) popular requests thereafter was to make the venerable Northwind database available too so I am pleased to say that as of right now, Northwind is up there too.

image

You will notice immediately that all of the Northwind tables (and the stored procedures and views too) have been moved into a schema called [Northwind] – this was so that they could be easily differentiated from the existing [AdventureWorks2012] objects.

I used an SQL Server Data Tools (SSDT) project to publish the schema and data up to this SQL Azure database; if you are at all interested in poking around that SSDT project then I have made it available on Codeplex for your convenience under the MS-PL license – go and get it from https://northwindssdt.codeplex.com/.

Using SSDT proved particularly useful as it alerted me to some aspects of Northwind that were not compatible with SQL Azure, namely that five of the tables did not have clustered indexes:

image

The beauty of using SSDT is that I am alerted to these issues before I even attempt a connection to SQL Azure. Pretty cool, no? Fixing this situation was of course very easy, I simply changed the following primary keys from being nonclustered to clustered:

  • [PK_Region]
  • [PK_CustomerDemographics]
  • [PK_EmployeeTerritories]
  • [PK_Territories]
  • [PK_CustomerCustomerDemo]

 

If you want to connect up then here are the credentials that you will need:

  • Server mhknbn2kdz.database.windows.net
  • Database AdventureWorks2012
  • User sqlfamily
  • Password sqlf@m1ly

You will need SQL Server Management Studio (SSMS) 2008R2 installed in order to connect or alternatively simply use this handy website: https://mhknbn2kdz.database.windows.net which provides a web interface to a SQL Azure server.

Do remember that hosting this database is not free so if you find that you are making use of it please help to keep it available by visiting Paypal and donating any amount at all to adventureworksazure@hotmail.co.uk. To make this easy you can simply hit this link and the details will be completed for you – all you have to do is login and hit the “Send” button. If you are already a PayPal member then it should take you all of about 20 seconds!

I hope this is useful to some of you folks out there. Don’t forget that we also have more data up there than in the conventional [AdventureWorks2012], read more at Big AdventureWorks2012.

@Jamiet 

AdventureWorks on Azure - Provided by the SQL Server community, for the SQL Server community!

Folders in SQL Server Data Tools

$
0
0

Recently I have begun a new project in which I am using SQL Server Data Tools (SSDT) and SQL Server Integration Services (SSIS) 2012. Although I have been using SSDT & SSIS fairly extensively while SQL Server 2012 was in the beta phase I usually find that you don’t learn about the capabilities and quirks of new products until you use them on a real project, hence I am hoping I’m going to have a lot of experiences to share on my blog over the coming few weeks. In this first such blog post I want to talk about file and folder organisation in SSDT.

The predecessor to SSDT is Visual Studio Database Projects. When one created a new Visual Studio Database Project a folder structure was provided with “Schema Objects” and “Scripts” in the root and a series of subfolders for each schema:

image

Apparently a few customers were not too happy with the tool arbitrarily creating lots of folders in Solution Explorer and hence SSDT has gone in completely the opposite direction; now no folders are created and new objects will get created in the root – it is at your discretion where they get moved to:

image

After using SSDT for a few weeks I can safely say that I preferred the older way because I never used Solution Explorer to navigate my schema objects anyway so it didn’t bother me how many folders it created. Having said that the thought of a single long list of files in Solution Explorer without any folders makes me shudder so on this project I have been manually creating folders in which to organise files and I have tried to mimic the old way as much as possible by creating two folders in the root, one for all schema objects and another for Pre/Post deployment scripts:

image

This works fine until different developers start to build their own different subfolder structures; if you are OCD-inclined like me this is going to grate on you eventually and hence you are going to want to move stuff around so that you have consistent folder structures for each schema and (if you have multiple databases) each project. Moreover new files get created with a filename of the object name + “.sql” and often people like to have an extra identifier in the filename to indicate the object type:

image

The overall point is this – files and folders in your solution are going to change. Some version control systems (VCSs) don’t take kindly to files being moved around or renamed because they recognise the renamed/moved file simply as a new file and when they do that you lose the revision history which, to my mind, is one of the key benefits of using a VCS in the first place. On this project we have been using Team Foundation Server (TFS) and while it pains me to say it (as I am no great fan of TFS’s version control system) it has proved invaluable when dealing with the SSDT problems that I outlined above because it is integrated right into the Visual Studio IDE. Thus the advice from this blog post is:

If you are using SSDT consider using an Visual-Studio-integrated VCS that can easily handle file renames and file moves

I suspect that fans of other VCSs will counter by saying that their VCS weapon of choice can handle renames/file moves quite satisfactorily and if that’s the case…great…let me know about them in the comments. This blog post is not an attempt to make people use one particular VCS, only to make people aware of this issue that might rise when using SSDT.

More to come in the coming few weeks!

@jamiet

Publish Profile Files in SQL Server Data Tools (SSDT)

$
0
0

I have been using SQL Server Data Tools (SSDT) both at work and on some hobby projects for quite a few weeks now and of all the new features I have to say the one that I am appreciating the most is Publish Profile files. I have been searching around on MSDN for an article that explains Publish Profile files but it seems no such article exists so I’ll attempt to surmise here.

Publish Profile files are, essentially, a collection of all the property key-value pairs that are needed to deploy a database model (i.e. a .dacpac) to some target database. Those properties include (but are not limited to):

  • database name
  • connection string
  • whether or not to publish SSDT projects on which the current project has a dependency
  • Recreate the database from scratch (or not)
  • Backup before deploy
  • Drop unknown objects in target
  • SQLCMD Variables

Those that have used the predecessor to SSDT, Visual Studio Database Projects, will be familiar with a lot of those properties however in that case the properties had to be specified on a case-by-case basis; typically in an msbuild script or similar. Often those scripts are not maintained by a developer – rather they are maintained by a DevOps team that are not familiar with the code being deployed and as a developer myself that’s not a situation that I’m at all comfortable with. On my most recent project where Visual Studio Database Projects were being used I faced the maddening situation where every new SQLCMD variable added to a project required an email to be sent to the DevOps team to ask them to update their scripts accordingly. As you can imagine human errors crept in (on our side more than the DevOps side) and we ended up deploying projects with the wrong SQLCMD values. Moreover, we had to deal with different DevOps folks and often they would store the values in different places; totally infuriating, believe me.

Publish Profile files make this process much easier because we can define all those properties on a per-environment basis and keep them in a dedicated Publish Profile file. The obvious benefit then is that a Publish Profile file abstracts all of the environment-specific information into a single file so deploying an SSDT project now requires only two things; the build output (i.e. a .dacpac file) and a Publish Profile file:

>sqlpackage.exe /sf:MyDB.dacpac /pr:DEV.publish.xml

The implied benefit (and this is what I really like about them) is that Publish Profile files are a source code artefact that a developer maintains the same as they would any other source code artefact, all that the DevOps people need are the build output (i.e. a .dacpac file) and an appropriately named Publish Profile file. Developers are now wholly in charge of how their code gets deployed which keeps them happy and the DevOps people have less work to do – so they’re a happy bunch too! I’m not saying that the wrong values won’t ever be supplied but at least now we know exactly where to go to fix those errors.

SSDT also provides a friendly UI for maintaining these Publish Profile files. Double-click on one and this UI appears:

image

Its fairly self-explanatory to fill these things out. A connection string, a database name and values for each SQLCMD variable defined within the project and you’re pretty much there. (I have written previously about one other benefit of Publish Profile files - that they can be used to make SQLCMD variables mandatory. Read more at SQL Server Data Tools does support required variables.)

One minor downside of Publish Profile files is that they get created in the root of your SSDT project (I have griped about this previously at Folders in SQL Server Data Tools) so the convention that I have been using is to create a folder called Publish in each SSDT project and move all Publish Profile files into there.

image

Hopefully this has given you a small taster of what Publish Profile files are all about. I’ll probably share some msbuild scripts that we’re using to deploy these things in a later blog post.

@Jamiet 

P.S. As an aside, I have requested that the SSIS/SSAS/SSRS teams adopt the Publish Profile file approach in future iterations of their products. If you think that that is something you would like to see happen then click through, vote and leave a comment.

Redistribution of sqlpackage.exe [SSDT]

$
0
0

This is a short note for anyone that may be interested in redistributing sqlpackage.exe. If this isn’t you then no need to keep reading. Ostensibly this is here for anyone that bingles for this information.

sqlpackage.exe is a command-line that ships with SQL Server Development Tools (SSDT) in SQL Server 2012 and its main purpose (amongst other things) is to deploy .dacpac files from the command-line. Its quite conceivable that one might want to install only sqlpackage.exe rather than the full SSDT suite (for example on a production server) and I myself have recently had that need. I enquired to the SSDT product team about the possibility of doing this. I said:

Back in VS DB Proj days it was possible to use VSDBCMD.exe on a machine that did not have the full VS shell install by shipping lots of pre-requisites along for the ride (details at How to: Prepare a Database for Deployment From a Command Prompt by Using VSDBCMD.EXE).

Is there a similar mechanism for using VSDBMCD.exe’s replacement, sqlpackage.exe?

here was the reply from Barclay Hill who heads up the development team:

Yes, SQLPackage.exe is the analogy of VSDBCMD.exe. You can acquire separately, in a stand-alone package, by installing DACFX.

You can get it from:

You will notice it has dependencies on SQLDOM and SQLCLRTYPES.  WebPI will install these for you, but it is al carte on the feature pack.

So, now you know. I didn’t enquire about licensing of DACFX but given SSDT is free I am going to assume that the same applies to DACFX too.

@Jamiet

UPDATE: Gert Drapers has posted an article Headless MSBuild Support for SSDT (*.sqlproj) Projects in which he describes five seperate installations that need to be performed in order to run SSDT deployment without installing Visual Studio:

  • dacframework.msi
  • SQLDOM.msi
  • SQLLS.msi
  • SQLSysClrTypes.msi
  • SSDTBuildUtilities.msi

(see Gert's article for links to those five installation files) 

Notice that two of those are mentioned in Barclay's quote above. I do not know if the other three are installed by WebPI or even whether they are required for sqlpackage.exe to work, one day I hope to get a clear answer on that from someone at Microsoft. Until that data comes, use the information here and in Gert's article to get your deployments working.

Smart defaults [SSDT]

$
0
0

I’ve just discovered a new, somewhat hidden, feature in SSDT that I didn’t know about and figured it would be worth highlighting here because I’ll bet not many others know it either; the feature is called Smart Defaults. It gets around the problem of adding a NOT NULLable column to an existing table that has got data in it – previous to SSDT you would need to define a DEFAULT constraint however it does feel rather cumbersome to create an object purely for the purpose of pushing through a deployment – that’s the situation that Smart Defaults is meant to alleviate.

The Smart Defaults option exists in the advanced section of a Publish Profile file:

image

The description of the setting is “Automatically provides a default value when updating a table that contains data with a column that does not allow null values”, in other words checking that option will cause SSDT to insert an arbitrary default value into your newly created NON NULLable column. In case you’re wondering how it does it, here’s how:

SSDT creates a DEFAULT CONSTRAINT at the same time as the column is created and then immediately removes that constraint:

ALTER TABLE [dbo].[T1]
   
ADD [C1] INT NOT NULL,
       
CONSTRAINT [SD_T1_1df7a5f76cf44bb593506d05ff9a1e2b] DEFAULT 0 FOR [C1];

ALTER TABLE [dbo].[T1] DROP CONSTRAINT [SD_T1_1df7a5f76cf44bb593506d05ff9a1e2b];

You can then update the value as appropriate in a Post-Deployment script. Pretty cool!

On the downside, you can only specify this option for the whole project, not for an individual table or even an individual column – I’m not sure that I’d want to turn this on for an entire project as it could hide problems that a failed deployment would highlight, in other words smart defaults could be seen to be “papering over the cracks”. If you think that should be improved go and vote (and leave a comment) at [SSDT] Allow us to specify Smart defaults per table or even per column.

@Jamiet

Bitmask data insertions in SSDT Post-Deployment scripts

$
0
0

On my current project we are using SQL Server Data Tools (SSDT) to manage our database schema and one of the tasks we need to do often is insert data into that schema once deployed; the typical method employed to do this is to leverage Post-Deployment scripts and that is exactly what we are doing.

Our requirement is a little different though, our data is split up into various buckets that we need to selectively deploy on a case-by-case basis. I was going to use a SQLCMD variable for each bucket (defaulted to some value other than “Yes”) to define whether it should be deployed or not so we could use something like this in our Post-Deployment script:

IF ($(DeployBucket1Flag) = 'Yes')
BEGIN
   :r .\Bucket1.data.sql
END
IF ($(DeployBucket2Flag) = 'Yes')
BEGIN
   :r .\Bucket2.data.sql
END
IF ($(DeployBucket3Flag) = 'Yes')
BEGIN
   :r .\Bucket3.data.sql
END

That works fine and is, I’m sure, a very common technique for doing this. It is however slightly ugly because we have to litter our deployment with various SQLCMD variables. My colleague James Rowland-Jones (whom I’m sure many of you know) suggested another technique – bitmasks. I won’t go into detail about how this works (James has already done that at Using a Bitmask - a practical example) but I’ll summarise by saying that you can deploy different combinations of the buckets simply by supplying a different numerical value for a single SQLCMD variable. Each bit of that value’s binary representation signifies whether a particular bucket should be deployed or not. This is better demonstrated using the following simple script (which can be easily leveraged inside your Post-Deployment scripts):

/* $(DeployData) is a SQLCMD variable that would, if you were using this in SSDT, be declared in the SQLCMD variables section of your 
project file. It should contain a numerical value, defaulted to 0.
 
In this example I have declared it using a :setvar statement. Test the affect of different values
by changing the :setvar statement accordingly.
 
Examples:
:setvar DeployData 1   will deploy bucket 1
:setvar DeployData 2   will deploy bucket 2 
:setvar DeployData 3   will deploy buckets 1 & 2
:setvar DeployData 6   will deploy buckets 2 & 3
:setvar DeployData 31  will deploy buckets 1, 2, 3, 4 & 5
*/
:setvar DeployData 0
DECLARE  @bitmask VARBINARY(MAX) = CONVERT(VARBINARY,$(DeployData));
IF (@bitmask & 1 = 1)
BEGIN     PRINT 'Bucket 1 insertions';
END
IF (@bitmask & 2 = 2)
BEGIN     PRINT 'Bucket 2 insertions';
END
IF (@bitmask & 4 = 4)
BEGIN     PRINT 'Bucket 3 insertions';
END
IF (@bitmask & 8 = 8)
BEGIN     PRINT 'Bucket 4 insertions';
END
IF (@bitmask & 16 = 16)
BEGIN     PRINT 'Bucket 5 insertions';
END

An example of running this using DeployData=6

image

The binary representation of 6 is 110. The second and third significant bits of that binary number are set to 1 and hence buckets 2 and 3 are “activated”.

Hope that makes sense and is useful to some of you!

@Jamiet

P.S. I used the awesome HTML Copy feature of Visual Studio’s Productivity Power Tools in order to format the T-SQL code above for this blog post.


CASTs become CONVERTs in computed columns with implications for SSDT

$
0
0

I discovered a peculiar little nuance in SQL Server yesterday that I think is worth sharing. Execute the following CREATE TABLE statement:

CREATE TABLE _t(c INT,
	[S_Profit] AS (CAST (1 AS DECIMAL (19, 6)))
);

If you then go to Object Explorer and script that table out:

image

you see this:

image

Notice how the definition of the [S_Profit] computed column is not the same as it was what we created the table, it is now a CONVERT rather than a CAST.

OK, so that behaviour might be considered a little strange but its hard to see why it might be a problem. Well, it actually did create a problem for me yesterday as I shall now explain.

On my current project we are using Publish in SQL Server Data Tools (SSDT) [and by “SSDT” I mean the database projects, not the Visual Studio shell around the SSIS/SSAS/SSRS stuff] to deploy our database schema. That schema included computed columns using CAST and hence every time we attempted a publish SSDT would compare the table definition in the project with the existing table in the target and notice that they were different. This can be better better illustrated using SSDT’s Schema Compare tool (which does essentially the same comparison as is done at publish time):

image

Notice where I have underlined in red that the table definition in my source uses a CAST yet in the target it was changed to a CONVERT the last time we published. Notice also, underlined in green, that another expression has been rewritten to take out parentheses. Here’s a similar case where DEFAULT constraints also get rewritten:

image

Another one, keywords in CHECK constraints get uncapitalised* and parentheses get added in:

image

At publish time SSDT will generate a script that will attempt to make the target look like the source hence it is going to be making the same changes to these computed columns, default constraints and check constraints every single time you publish. Also note that any dependent objects will get affected too; e.g. dependent views may get dropped and recreated – if those views have indexes on them and there is a lot of data in those indexes then your publish operations are going to take a longggggg time.

The point is, your SSDT publishes might be working fine yet doing a lot more work than they actually need to so I would encourage you to change the default constraints, check constraints and computed column definitions in your source code to whatever SQL Server rewrites it to. The Schema Compare tool is your friend when trying to do this.

UPDATE: There was a little confusion from someone on Twitter as to where the problem lies here. Its is not something that SSDT is doing incorrectly, the re-writing is being done by the database engine.

@Jamiet

*Is “uncapitalised” a word? What is the opposite of “capitalised”?

New version of SQL Server Data Tools is now available

$
0
0

If you don’t follow the SQL Server Data Tools (SSDT) blog then you may not know that two days ago an updated version of SSDT was released (and by SSDT I mean the database projects, not the SSIS/SSRS/SSAS stuff) along with a new version of the SSDT Power Tools. This release incorporates a an updated version of the SQL Server Data Tier Application Framework (aka DAC Framework, aka DacFX) which you can read about on Adam Mahood’s blog post SQL Server Data-Tier Application Framework (September 2012) Available. DacFX is essentially all the gubbins that you need to extract and publish .dacpacs and according to Adam’s post it incorporates a new feature that I think is very interesting indeed:

Extract DACPAC with data – Creates a database snapshot file (.dacpac) from a live SQL Server or Windows Azure SQL Database that contains data from user tables in addition to the database schema. These packages can be published to a new or existing SQL Server or Windows Azure SQL Database using the SqlPackage.exe Publish action. Data contained in package replaces the existing data in the target database.

In short, .dacpacs can now include data as well as schema. I’m very excited about this because one of my long-standing complaints about SSDT (and its many forebears) is that whilst it has great support for declarative development of schema it does not provide anything similar for data – if you want to deploy data from your SSDT projects then you have to write Post-Deployment MERGE scripts. This new feature for .dacpacs does not change that situation yet however it is a very important pre-requisite so I am hoping that a feature to provide declaration of data (in addition to declaration of schema which we have today) is going to light up in SSDT in the not too distant future.

Read more about the latest SSDT, Power Tools & DacFX releases at:

@Jamiet

Highlight Word add-in for Visual Studio 2010 [SSDT]

$
0
0

I’ve just been alerted by my colleague Kyle Harvie to a Visual Studio 2010 add-in that should prove very useful if you are an SSDT user. Its simply called Highlight all occurrences of selected word and does exactly what it says on the tin, you highlight a word and it shows all other occurrences of that word in your script:

image

There’s a limitation for .sql files (which I have reported) where the highlighting doesn’t work if the word is wrapped in square brackets but what the heck, its free, it takes about ten seconds to install….install it already!

@Jamiet

Big label generator

$
0
0

Sometimes I write blog posts mainly so that I can find stuff when I need it later. This is such a blog post.

Of late I have been writing lots of deployment scripts and I am fan of putting big labels into deployment scripts (which, these days, reside in SSDT) so one can easily see what’s going on as they execute. Here’s such an example from my current project:

image

which results in this being displayed when the script is run:

image

In case you care….PM_EDW is the name of one of our databases.

I’m almost embarrassed to admit that I spent about half an hour crafting that and a few others for my current project because a colleague has just alerted me to a website that would have done it for me, and given me lots of options for how to present it too:

image

http://www.patorjk.com/software/taag/#p=testall&f=Banner3&t=PM__EDW

Very useful indeed. Nice one! And yes, I’m sure there are a myriad of sites that do the same thing - I’m a latecomer, ok?

@Jamiet

Implementing SQL Server solutions using Visual Studio 2010 Database Projects – a compendium of project experiences

$
0
0

Over the past eighteen months I have worked on four separate projects for customers that wanted to make use of Visual Studio 2010 Database projects to manage their database schema.* All the while I have been trying to take lots of notes in order that I can write the blog post that you are reading right now – a compendium of experiences and tips from those eighteen months. I should note that this blog post should not necessarily be taken as a recommendation to actually use database projects in Visual Studio 2010 – it is intended to be useful for those of you that have already made the decision to use them; having said that, I do make recommendations as to actions I think you should take if you have made that decision.

First let’s be clear what we’re talking about here. Visual Studio Database Projects have been known by a few different names down the years, some of which you may be familiar with. If you have ever heard the terms datadude, DBPro, teamdata, TSData or Visual Studio Team System for Database Professionals then just know that all of these terms refer to the same thing, namely the project type highlighted below when starting a new project in Visual Studio:

image

From here onwards I am going to refer to Visual Studio Database projects and all the features therein simply as datadude because that’s a popular colloquial name (and is also much quicker to type). Know also that at the time of writing the features that I am talking about here are currently undergoing some changes ahead of the next release of SQL Server (i.e. SQL Server 2012) in which these features are mooted to be delivered under a new moniker - SQL Server Developer Tools (SSDT).

OK, with all those preliminaries out of the way let’s dig in.

Continuous Integration

Continuous Integration (CI) is a development practise that has existed for many years but in my experience has not been wholly embraced by the database community. The idea behind CI for databases is that every time a developer checks-in a piece of code be it a stored procedure, a table definition or whatever, the entire database project is built and then deployed to a database instance. Microsoft provide a useful article An Overview of Database Build and Deployment that goes some way to explaining how to setup your CI deployment.

CI is one of the fundamental tenets that underpins a lot of the things I talk about later in this blog post and hence gives rise to my first recommendation when using datadude:

Recommendation #1: Use Source Control and implement a Continuous Integration deployment

In an earlier draft of this blog post I outlined in detail the CI configuration from one of the aforementioned projects. Its not suitable for inclusion at this point in the current draft but I still think there is some useful information to be gleaned so I have included it below in “Appendix – An example CI configuration”.

Composite Projects

Each of the four aforementioned projects were brownfield projects meaning that each already encompassed some established, deployed, databases and they wanted to bring those databases under the control of datadude. Each project had thousands of objects across multiple databases and in this situation it is very likely that some of the stored procedures, views or functions will refer to objects in one of the other databases. The way to resolve those references is to use database references however once you have applied all of your database references it is still very possible that you will run into a situation where code in database A refers to an object in database B while at the same time database B refers to an object in database A. This is depicted in the following figure:

image

Here we have a view [DB1]..[View2] that selects data from [DB2]..[Table1] and a view [DB2]..[View1] that selects data from [DB1]..[Table1]. Datadude does not allow a database reference from [DB2] to [DB1] if there is already a database reference from [DB2] to [DB1] and hence will return an error akin to:

  • SQL03006: View: [dbo].[View1] has an unresolved reference to object [DB1].[dbo].[Table1].

image

We have the proverbial chicken-and-egg problem, [DB1] can’t be created before [DB2] and vice versa. This problem is solved by using Composite Projects (not to be confused with Partial Projects) which allow you to split objects that are intended to be in the same database over multiple datadude projects. I could go over how you set one of these things up but there’s really no need because there is a rather excellent walkthrough on MSDN at Walkthrough: Partition a Database Project by Using Composite Projects; the reason for me mentioning it here is to make you aware that composite projects exist and of the problem that they solve. If you are introducing datadude into a brownfield project then it is highly likely that you are going to require composite projects so learn them and learn them good.

One important last note about composite projects is to answer the question “How does the tool know that the multiple projects refer to the same database?” The answer is given at the walkthrough that I linked to above; namely, it says:

Do not specify server variables and values or database variables and values when you define references in a composite project. Because no variables are defined, the referenced project is assumed to share the target server and database of the current project.

“Do not specify server variables and values or database variables and values when you define references in a composite project. Because no variables are defined, the referenced project is assumed to share the target server and database of the current project.”

So now you know! To put it another way, if you reference one project from another and don’t tell datadude that the two projects refer to different databases then it assumes they refer to the same database.

Code Analysis

Datadude provides the ability to analyse your code projects for code in stored procedures and functions that it considers to be inferior and highlight it – this feature is called Code Analysis. Note that Code Analysis will not highlight code that is syntactically incorrect (datadude does that already, which may well be considered its core feature), it highlights code that is syntactically correct but may be considered defective when executed. Specifically Code Analysis will highlight the following perceived code defects (click through on the links for explanations of why these are considered code defects):

In my opinion the best aspect of Code Analysis is that it can be run as part of your Continuous Integration deployment meaning that if anyone checks in some deficient code, BOOM, your CI deployment fails and the developer is left red-faced. Nothing else has increased the code quality on my projects quite like running Code Analysis as part of a CI deployment.

Hopefully I have convinced you that turning on Code Analysis is a good idea. If you agree then head to the project properties and check the box labelled Enable Code Analysis on Build. I also recommend checking the Treat warnings as errors boxes otherwise you’ll find that undisciplined developers will simply ignore the warnings.

Enable datadude code analysis

N.B. Incidentally if you have time I highly recommend that you go and read the blog post I linked to there – Discipline Makes Strong Developers by Jeff Atwood. I’ve read many thousands of blog posts in my time and that is the one that has influenced me more than any other.

Turning on Code Analysis on a greenfield project is a no-brainer. On a brownfield project its not quite so easy – on a recent engagement I moved a single database into datadude and turned on Code Analysis which immediately found over two thousand perceived code defects. I generally abhor the use of that famous maxim if it aint broke, don’t fix it in our industry but on occasions like this you may be well advised to heed that advice and leave well alone for fear of breaking code that does what it is supposed to (no matter how inefficiently it does it). Instead you do have the option to suppress Code Analysis warnings/errors:

Suppress datadude code analysis

I advise using Code Analysis suppression sparingly. Recently I discovered that one of the developers on my team had decided it was OK to simply suppress every error that was thrown by Code Analysis without first investigating the cause. I was not amused!

Recommendation #2: Turn on Code Analysis

Realising the value of idempotency

An operation is considered idempotent if it produces the same result no matter how many times that operation is applied; for example, multiplication by a factor of one is an idempotent operation – no matter how many times you multiple a number by one the result will always be the same.

Idempotency is a vital facet of database deployment using datadude. Datadude tries to ensure that no matter how many times you deploy the same project the state of your database should be the same after each deployment. The implication here is that during a deployment datadude will examine the target database to see what changes (if any) need to be made rather than simply attempting to create lots of objects; if all the objects already exist nothing will be done. In my opinion this is the single biggest benefit of using datadude – you don’t have to determine what needs to be done to change your database schema to the desired state, datadude does it for you.

If I have convinced you about the value of idempotency within datadude then you should also realise that the same rigour should be applied to data as well. Datadude provides Post-Deployment scripts that allow you to deploy data to your schema however there is no inbuilt magic here – datadude will simply go and run those scripts as-is, it will not try and comprehend the contents of those scripts. What this means is that you, the developer, are responsible for making your Post-Deployment scripts idempotent and the easiest way to do that is to employ the T-SQL MERGE statement.

T-SQL’s INSERT is not sufficient as it will work once and thereafter fail as it will be attempting to insert already inserted data; this gives rise to my third recommendation:

Recommendation #3: When running your deployment in a test environment, run it more than once.

No-brainer Recommendations

I consider Code Analysis and Idempotency to be so important that I called them out as dedicated headlines. In this section I’ll outline some additional simple measures that you can undertake and which will, if employed correctly, have a profound effect on the success of your datadude projects.

Putting a build number into the DB

I find it is very useful to maintain a log of deployments that have been made to a database and my chosen method is to use a Post-Deployment script to insert a value into some table. Here’s the definition of the table I use for this:

CREATE TABLE [dbo].[DeployLog]
(
  
[BuildId]           NVARCHAR(50)
[DeployDatetime]    SMALLDATETIME
CONSTRAINT  PK_dboDeployLog PRIMARY KEY ([DeployDatetime])
)

In my Post-Deployment script I will use:

INSERT [dbo].[DeployLog]([BuildId],[DeployDatetime])
VALUES ('$(BuildId)',GETDATE());

to insert a row into that table during every deployment. $(BuildId) is a variable defined in the .sqlcmdvars file of my project:

image

Here is what we see inside that file:

image

The $(BuildId) variable has been defined with a default value of UNKNOWN and hence subsequent deployments from Visual Studio will result in the following:

image

On first glance that might not seem particularly useful however it comes into its own if you are doing CI deployments (see recommendation #1) because each build in a CI environment will result in a new build identifier. The following command-line call to vsdbcmd.exe is how deployments are generally done using datadude, note the presence of the /p:BuildId switch:

..\Tools\VSDBCMD\vsdbcmd.exe /Action:Deploy /ConnectionString:"Data Source=.;Integrated Security=True;Pooling=False" /p:BuildId="some-value" /DeployToDatabase:+ /ManifestFile:.\FinanceDB\sql\release\FinanceDB.deploymanifest

Your CI tool should be able to replace “some-value” with an identifier for the current build (that’s outside the scope of this blog post but any CI tool worth its salt will be able to do this) – when the deployment executes that value will then make its way into your [dbo].[DeployLog] table and you will have a self-maintaining history of all the deployments (datetime & build identifier) that have been made to your database.

Recommendation #4: Maintain an automated history of your deployments

Use Schema View

It is natural to navigate through all of the objects in your database project using Solution Explorer however datadude provides a better mechanism for doing just that – the Schema View window.

image

Schema View provides a logical view of all the objects defined in your database project regardless of which file they may be defined in. That is very useful for many reasons, not least because it makes it easy to locate whichever object you are after – that’s advantageous if multiple objects are defined in the same file. Moreover if some files have property BuildAction=”Not In Build” (see later) they won’t show up in Schema View (this is a good thing by the way). Schema View is also the place that operations such as refactoring and dependency analysis are launched from.

Some people think that it is important that the name of each file in a datadude project should accurately reflect the object defined within. I disagree; object renames mean that maintaining the filenames becomes laborious and having the Schema View means you never have to use the filenames to navigate your project anyway.

One final reason to use Schema View is the External Elements button:

image

Toggling this button on means that objects in referenced projects show up in the project that they are referenced from (this is particularly useful if you are using Composite Projects). Note in the following screenshot how the object [dbo].[t1] in project Database2 appears in the [dbo] schema of Database3 – that’s because Database3 has a reference to Database2.

image

For those reasons my fifth recommendation is:

Recommendation #5: Use Schema View in preference to Solution Explorer

You will still need Solution Explorer to navigate files that do not contain database objects (e.g. Post-Deployment scripts) but ordinarily you should spend most of your time interacting with Schema View.

Make liberal use of PRINT statements in Pre/Post-Deployment Scripts

When you deploy a datadude project datadude will take care of telling you what it is up to. For example, the following screenshot shows the output from deploying the already discussed [dbo].[DeplogLog]:

image

Of course it only does this for objects that it knows about and that doesn’t include anything in your Pre or Post \deployment scripts so you need to take responsibility for outputting pertinent information from those scripts. Here I have amended the script that inserts into [dbo].[DeployLog]:

SET NOCOUNT ON;
INSERT [dbo].[DeployLog]([BuildId],[DeployDatetime])
VALUES ('$(BuildId)',GETDATE());
PRINT CAST(@@ROWCOUNT as NVARCHAR(5)) + N'rows inserted into [dbo].[DeployLog], BuildId=$(BuildId)';

This gives us much more useful output:

image

Adding PRINT statements to your Pre & Post Deployment scripts is so easy it really is a no-brainer and hence my next recommendation is:

Recommendation #6: Any action in a Pre or Post-Deployment Script should use PRINT to state what has been done

Output variable values in your Pre-Deployment script

This is in the same vein as the previous bullet-point – output as much information as is possible. In this case we’re talking about outputting the values of all variables that are stored in the .sqlcmdvars file; first, a reminder of what’s in that file:

image

Here is the contents of my amended Pre-Deployment Script:

PRINT 'DefaultDataPath=$(DefaultDataPath)';
PRINT 'DatabaseName=$(DatabaseName)';
PRINT 'DefaultLogPath=$(DefaultLogPath)';
PRINT 'BuildId=$(BuildId)';

And the resultant output:

image

This is the sort of simple amendment that will pay off in spades later in your project (especially if you are supplying many values from the command-line) and again, its so easy to do it there really is no reason not to. Just remember to update your Pre-Deployment script whenever you add new variables to .sqlcmdvars.

Recommendation #7: Output the value of all variables in your Pre-Deployment script

One Object Per File

Datadude doesn’t restrict what can go in a file, for example the following file, “t.table.sql”, defines three objects; a table, a primary key and a view:

image

Even though they’re all defined in the same file they show up in Schema View separately (one of the aforementioned benefits of using Schema View):

image

That said, just because you can doesn’t mean that you should. I prefer to go for one object per file for the simple reason that its easier to track the history of an object via Source Control. Moreover, if an object is no longer required then it is a simple change to just remove the file containing that object from the build (see “Don’t delete anything from your project” later) as opposed to editing a file to remove all traces of an object.

Recommendation #8: Each database object should be defined in a dedicated file

Time your Pre and Post Deployment Scripts

Its always useful to know where time is spent when doing deployments, in my experience the majority of time spent is in the Post-Deployment script (your mileage may vary of course). An easy win is to output the time taken to run your Pre and Post Deployment scripts. Adapt your Pre-Deployment script so that it looks something like this:

DECLARE @vPreDeploymentStartTime DATETIME = GETDATE();
PRINT '****************Begin Pre-Deployment script at ' +CONVERT(VARCHAR(30),GETDATE(),120) + '***********************';

/*Call other scripts from here using SQLCMD's :r syntax
Example:      :r .\myfile.sql                          
*/

PRINT 'Pre-Deployment duration = ' + CONVERT(VARCHAR(5),DATEDIFF(ss,@vPreDeploymentStartTime,GETDATE())) + ' seconds';
PRINT '****************End Pre-Deployment script at ' +CONVERT(VARCHAR(30),GETDATE(),120) + '***********************';

then do similar for your Post-Deployment script. When you deploy your output will include the following:

image

Note the lines:

    ****************Begin Pre-Deployment script at 2011-12-31 20:00:34***********************
    Pre-Deployment duration = 0 seconds
    ****************End Pre-Deployment script at 2011-12-31 20:00:34***********************
   

    ****************Begin Post-Deployment script at 2011-12-31 20:00:34***********************
    Post-Deployment duration = 0 seconds
    ****************End Post-Deployment script at 2011-12-31 20:00:34***********************

In this particular case its not all that useful to know that the deployment took 0 seconds but if and when your deployments snowball to many minutes it will be useful to know how long your scripts are taking at which point you can investigate further by timing each individual step in your Pre and Post Deployment scripts.

Recommendation #9: Time your deployments and output the timings

Use sqlcmdvars and the command-line as much as possible

Hardcoding any value into a piece of code is a fraught practise; you should assume that values previously thought to be constant may not be so in the future. You can protect yourself from future changes by storing all literal values as variables in your .sqlcmdvars file. Sure, you can supply default values for those variables but you have the added advantage that they can be overridden from the command-line when deploying using vsdbcmd.exe. Moreover, if you have values that are hardcoded in multiple places in your code then specifying those values in .sqlcmdvars ensures that your code adheres to the principle of DRY. Lastly, if values are stored in the .sqlcmdvars file then you can output them at deploy time (see recommendation #7).

Recommendation #10: All literal values should be stored in your .sqlcmdvars file

Every developer gets their own development database

In most SQL Server development shops that I’ve been on all developers work against a single centralised development database. To me this is an antiquated way of working because its possible that work one person is doing can conflict with that of someone else, I find it much better for every developer to work in isolation and then use the CI deployment to check that one’s code is not in conflict with anyone else’s. Datadude supports (nay encourages) this way of working with the notion of an Isolated Development Environment:

image

Every developer should configure their isolated development environment which, typically, would be their local instance. And so to my next recommendation:

Recommendation #11: Every developer should use the Isolated Dev Environment settings in order to author their code

Incidentally, if every developer has their own development database and you are following my earlier recommendation to use a [DeployLog] table then you can track how often a developer is bothering to deploy and test their code. On a recent project we used this evidence in a (ahem) discussion with a developer who tried to convince us that he was testing his code sufficiently even though he was repeatedly causing the CI deployment to fail.

Don’t delete anything from your project

When projects are no longer required in your database then intuitively it makes sense to remove the file containing that object from the datadude project, I would however like to suggest a different approach. Rather than removing a file just change the Build property to “Not in Build”:

image

This has the advantage that your project maintains some semblance of history of what objects have been removed from your database – that can be useful to anyone inheriting your code in the future.

Recommendation #12: Use “Not in Build” to remove an object from your database

Build and Deploy your datadude projects outside of Visual Studio

Building and deploying your datadude projects within Visual Studio can become a real time hog; in my experience its not unusual for deployments to take many minutes and your Visual Studio environment will be unavailable for further development work during that time. For that reason I recommend investing some time in writing some msbuild scripts that will build and deploy your project(s) from the command-line. Here are some examples that you can adapt for your own use, firstly a script to build a solution:

<?xmlversion="1.0"encoding="utf-8"?>
<!--Execute using:
msbuild SolutionBuild.proj
-->
<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
          DefaultTargets="Build">
  <!--Notes:
      When doing .net development Visual Studio Configurations are particularly useful because they can affect
      how the code is executed (i.e. under the Debug configuration
      debug symbols can be used to step through the code (something like that anyway - I don't know too much about that
      stuff).
      In DBPro, Configurations are less relevant because there is no such thing as debugging symbols. Nonetheless, they
      can still be usefulfor times when you want to do different things (e.g. you might want to run Code Analysis in
      a debug situation but not in a releasesituation. There is a useful thread on this here:
      "Debug vs Release" http://social.msdn.microsoft.com/Forums/en-US/vstsdb/thread/a0ec0dc0-a907-45ba-a2ea-d2f0175261a7
    
      Note that Visual Studio Configurations should not be used to maintain different settings per environment.
      The correct way to do that is to maintain
      seperate .sqlcmdvars files per environment and then choose which one to use at deployment time when using
      vsdbcmd.exe (use syntax "/p:SqlCommandVariablesFile=$(ProjectName)_$(Environment).sqlcmdvars")
  -->
  <ItemGroup>
    <!--List all the configurations here that you want to build-->
    <ConfigInclude="Debug" />
    <ConfigInclude="Release" />
  </ItemGroup>
  <TargetName="Build">
    <MessageText="Building %(Config.Identity) configuration..."/>
    <MSBuildProjects=".\Lloyds.UKTax.DB.sln"Properties="Configuration=%(Config.Identity)" />
  </Target>
</Project>

and secondly a script that will deploy a datadude project:

<?xmlversion="1.0"encoding="utf-8"?>
<!--Execute using:
msbuild SolutionDeploy.proj /Target:Deploy
-->
<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
          DefaultTargets="Build;Deploy">
  <PropertyGroup>
    <!--At time of writing I don't see a reason for anything else to be used but that may change in the future hence why this
      is a property and hence can be overriden.-->
    <Configuration>Debug</Configuration>
    <DevServer>Data Source=GBS0039182\GLDDEV01;Integrated Security=True;Pooling=False</DevServer>
  </PropertyGroup>
 
  <ItemGroup>
    <ProjectToBuildInclude="SolutionBuild.proj" />
  </ItemGroup>

  <!--Notes:
        Add a <DbProj> item for every database project (.dbproj) that needs to be deployed. They will get deployed in the
        order that they are listed
         thus it is your responsibility to make sure they are listed in the correct order (respecting dependency order).
        %Identity is a metadata reference. It refers to the name of the item (i.e. Include="The bit that goes here is the
          identity")
        Note also that whatever you put for Include is important. Include="dev_thomsonj" means the project will only get
      deployed if thedeployment is being executed by username=dev_thomsonj-->
  <ItemGroup>
    <DbProjInclude="username">
      <DbName>MyDB</DbName>
      <ProjectName>MySoln.MyDB</ProjectName>
      <OutputPath>\%(ProjectName)\sql\$(Configuration)\\cf1 </OutputPath>
      <DeployConnStr>Data Source=localhost;Integrated Security=True;Pooling=False</DeployConnStr>
    </DbProj>
  </ItemGroup>

  <TargetName="Build">
    <MSBuildProjects="@(ProjectToBuild)" />
  </Target>
 
  <TargetName="Deploy">
    <!--Notes:
          09 is the hex code for TAB, hence all of the %09 references that you can see. See http://asciitable.com/
            for more details.
    -->
    <MessageText="USERNAME=$(USERNAME)" />
    <MessageCondition="'%(DbProj.Identity)'==$(USERNAME)"Text="Deploying:
     Project%09%09%09:  %(DbProj.ProjectName)  
     DbName%09%09%09:  %(DbProj.DbName)
     From OutputPath%09%09:  %(DbProj.OutputPath)
     To ConnStr%09%09:  %(DbProj.DeployConnStr)
     By%09%09%09:  %(DbProj.Identity)"
     />
    <ExecCondition="'%(DbProj.Identity)'==$(USERNAME)"Command="&quot;$(VSINSTALLDIR)\vstsdb\deploy\vsdbcmd.exe&quot;
            /Action:Deploy /ConnectionString:&quot;%(DbProj.DeployConnStr)&quot; /DeployToDatabase+
            /manifest:&quot;.%(DbProj.OutputPath)%(DbProj.ProjectName).deploymanifest&quot; /p:TargetDatabase=%(DbProj.DbName)
            /p:Build=&quot;from cmd line&quot;" />
  </Target>
</Project>

Writing these scripts may appear to be laborious but they’ll save you heaps of time in the long run.

Recommendation #13: Build and deploy to your development sandbox using scripts

UPDATE: Upon reading this blog post Mordechai Danielov wrote a follow-up in which he published a useful script that builds a series of projects using Powershell. Its at building your database solutions outside of Visual Studio.

Useful links

Over the years I’ve collected some links to MSDN articles that have proved invaluable:

Datadude bugs

Like any substantial piece of software datadude is not without bugs. Many of the issues I have found are concerned with the datadude interpreter not correctly parsing T-SQL code, here’s a list of some bugs that I have found down the years:

Some of these bugs were reported a long time ago and may well have been fixed in later service packs.

Previous datadude blog posts

I have blogged on datadude quite a bit in the past:

Summing up

This has been an inordinately large blog post so if you’ve read this far – well done. For easy reference, here are all the recommendations that I have made:

  1. Use Source Control and implement a Continuous Integration deployment
  2. Turn on Code Analysis
  3. When running your deployment in a test environment, run it more than once
  4. Maintain an automated history of your deployments
  5. Use Schema View in preference to Solution Explorer
  6. Any action in a Pre or Post-Deployment Script should use PRINT to state what has been done
  7. Output the value of all variables in your Pre-Deployment script
  8. Each database object should be defined in a dedicated file
  9. Time your deployments and output the timings
  10. All literal values should be stored in your .sqlcmdvars file
  11. Every developer should use the Isolated Dev Environment settings in order to author their code
  12. Use “Not in Build” to remove an object from your database
  13. Build and deploy to your development sandbox using scripts

I really hope this proves useful because its taken a good long while to get it published Smile If you have any feedback then please let me know in the comments.

Thanks for reading!

@jamiet

* When I started writing this blog post the first sentence was “Over the past six months I have worked on two separate projects for customers that wanted to make use of Visual Studio 2010 Database projects to manage their database schema.” as opposed to what it is now: “Over the past eighteen months I have worked on four separate projects…” Yes, that’s how long its taken to write it! Smile

Appendix – An example CI configuration

As stated above, an earlier draft of this blog post included full details of the CI configuration from one of the projects that I have worked on. Although it may repeat some of what has already been said I have included that text below.

==============================================================

Introduction

This project has invested heavily in using a Continuous Integration (CI) approach to development. What that means, succinctly, is that whenever someone checks-in some code to our source control system an automated build process is kicked off that constructs our entire system from scratch on a dedicated server. CI is not a new concept but it is fairly rare that anyone applies the same rigour to their database objects as they do to so-called “application code” (e.g. the stuff written in .Net code) and on this project we have made a conscious decision to properly build our databases as part of the CI build.

Datadude employs a declarative approach to database development. In other words you define what you want database schema to look like and datadude will work out what it needs to do to your target in order to turn it into what you have defined. What this means in practice is that you only ever write CREATE … DDL statements rather than IF <object-exists> THEN ALTER …ELSE CREATE … statements which is what you may have done in the past.

Here’s our CI environment setup:

  • SubVersion (SVN) is being used for source control
  • Hudson, an open source CI server, is being used to orchestrate our whole CI environment. It basically monitors our SVN repository and when it spots a checked-in file, kicks off the CI build
  • Our CI scripts (the stuff that actually does the work) are written using msbuild
  • We have 2 msbuild scripts:
    • Build.proj which is responsible for:
      • Compiling all our .Net website code
      • Building/Compiling our datadude projects  (every datadude project file is a msbuild-compliant script)
    • Deploy.proj which is responsible for:
      • Restoring latest database backups from our production environment into our CI environment
      • Deploying our built datadude projects on top of those restored backups
      • Build a folder structure to hold all the artefacts that get deployed
      • Creating folder shares
      • Moving SSIS packages into folder structure
      • Deploying SSRS reports to our SSRS server
      • Deploy our Analysis Services cube definitions to our Analysis Server
  • Both Build.proj and Deploy.proj get executed by our CI build

Building datadude projects

Datadude makes it very easy to build datadude projects in a CI environment because they are already msbuild-compliant; its simply a call to the MSBuild task, passing in the location of the solution file as an argument. We use the Release configuration (although there is no particular reason for you to do the same – purely your choice):

<TargetName="Database">
  <!--Build database projects and copy output to staging -->
  <MessageText="*****Building database solution" />
  <MSBuildProjects="..\src\SQL\DatabaseSolution.sln"Properties="Configuration=Release" />
</Target>

That’s it! The output from a datadude build includes a number of files but the most important one is a .dbschema file which is an XML representation of all the objects in your database.

Deploying the output from a built datadude project

This is a little more difficult. We *could* simply use the MSBuild task to call our deployment script as we do for build script (see above) but the problem with that is that there are many pre-requisites (including datadude itself) and we don’t want to install Visual Studio and all the assorted paraphernalia onto our various environments. Instead we chose to make use of a command-line tool called VSDBCMD.exe to deploy datadude projects. VSDBCMD does basically the same job as what happens if you were to right-click on a datadude project in Visual Studio and select “Deploy” i.e. It compares the output of a build (A) to the target database (B) and works out what it needs to do to make B look like A. It then produces a .sql script that will actually make those requisite changes, then goes and executes it.

The difficulty comes in VSDBCMD.exe having its own list of file dependencies that are listed at MSDN article How to: Prepare a Database for Deployment From a Command Prompt by Using VSDBCMD.EXE, thankfully a much smaller list then if we were using the MSBuild task.

image

Some of those files, namely:

  • Sqlceer35en.dll
  • Sqlceme35.dll
  • Sqlceqp35.dll
  • Sqlcese35.dll
  • System.Data.SqlServerCe.dll

get installed with SQL Server CE. We bundle along the x86 & x64 installers for SQL Server CE along with all the rest of our deployment artefacts and then, as part of Deploy.proj, install them like so:

<ExecCommand='msiexec /passive /l* "$(SetupLogDirectory)\SSCERuntime_x86-ENU.log" /i "$(BuildDir)\Vendor\SSCERuntime_x86-ENU.msi"' />
<ExecCondition="$(X64)"Command='msiexec /passive /l* "$(SetupLogDirectory)\SSCERuntime_x64-ENU.log" /i "$(BuildDir)\Vendor\SSCERuntime_x64-ENU.msi"' />

That takes care of some of the dependencies but we still have to take care of:

  • DatabaseSchemaProviders.Extensions.xml
  • Microsoft.Data.Schema.dll
  • Microsoft.Data.Schema.ScriptDom.dll
  • Microsoft.Data.Schema.ScriptDom.Sql.dll
  • Microsoft.Data.Schema.Sql.dll
  • Microsoft.SqlServer.BatchParser.dll

as well as the actual VSDBCMD.exe file itself. Quite simply we keep those files in SVN and then bundle them along with all our deployment artefacts (I won’t show you how we do that because its out of the scope of this post and besides if you’re at all proficient with msbuild then you’ll know how to do that and if you’re not, well, why are you reading this?)

==============================================================

Editing sqlcmdvariable nodes in SSDT Publish Profile files using msbuild

$
0
0

Publish profile files are a new feature of SSDT database projects that enable you to package up all environment-specific properties into a single file for use at publish time; I have written about them before at Publish Profile Files in SQL Server Data Tools (SSDT) and if it wasn’t obvious from that blog post, I’m a big fan!

As I have used Publish Profile files more and more I have realised that there may be times when you need to edit those Publish profile files during your build process, you may think of such an operation as a kind of pre-processor step. In my case I have a sqlcmd variable called DeployTag, it holds a value representing the current build number that later gets inserted into a table using a Post-Deployment script (that’s a technique that I wrote about in Implementing SQL Server solutions using Visual Studio 2010 Database Projects – a compendium of project experiences– search for “Putting a build number into the DB”).

Here are the contents of my Publish Profile file (simplified for demo purposes) :

image

Notice that DeployTag defaults to “UNKNOWN”.

On my current project we are using msbuild scripts to control what gets built and what I want to do is take the build number from our build engine and edit the Publish profile files accordingly. Here is the pertinent portion of the the msbuild script I came up with to do that:

  <ItemGroup>    <Namespaces Include="myns">      <Prefix>myns</Prefix>      <Uri>http://schemas.microsoft.com/developer/msbuild/2003</Uri>    </Namespaces>  </ItemGroup>  <Target Name="UpdateBuildNumber">    <ItemGroup>      <SSDTPublishFiles Include="$(DESTINATION)\**\$(CONFIGURATION)\**\*.publish.xml" />    </ItemGroup>    <MSBuild.ExtensionPack.Xml.XmlFile Condition="%(SSDTPublishFiles.Identity) != ''"                                       TaskAction="UpdateElement"                                       File="%(SSDTPublishFiles.Identity)"                                       Namespaces="@(Namespaces)"                                        XPath="//myns:SqlCmdVariable[@Include='DeployTag']/myns:Value"                                        InnerText="$(BuildNumber)"/>  </Target>

The important bits here are the definition of the namespace http://schemas.microsoft.com/developer/msbuild/2003:

image

and the XPath expression //myns:SqlCmdVariable[@Include='DeployTag']/myns:Value:

image

Some extra info:

Hope this is useful!

@Jamiet

Database unit testing is now available for SSDT

$
0
0

Good news was announced yesterday for those that are using SSDT and want to write unit tests, unit testing functionality is now available. The announcement was made on the SSDT team blog in post Available Today: SSDT—December 2012. Here are a few thoughts about this news.

Firstly, there seems to be a general impression that database unit testing was not previously available for SSDT – that’s not entirely true. Database unit testing was most recently delivered in Visual Studio 2010 and any database unit tests written therein work perfectly well against SQL Server databases created using SSDT (why wouldn’t they – its just a database after all). In other words, if you’re running SSDT inside Visual Studio 2010 then you could carry on freely writing database unit tests; some of the tight integration between the two (e.g. right-click on an object in SQL Server Object Explorer and choose to create a unit test) was not there – but I’ve never found that to be a problem. I am currently working on a project that uses SSDT for database development and have been happily running VS2010 database unit tests for a few months now.

All that being said, delivery of database unit testing for SSDT is now with us and that is good news, not least because we now have the ability to create unit tests in VS2012. We also get tight integration with SSDT itself, the like of which I mentioned above. Having now had a look at the new features I was delighted to find that one of my big complaints about database unit testing has been solved. As I reported here on Connect a refactor operation would cause unit test code to get completely mangled. See here the before and after from such an operation:

20110516 Refacoring preview changes

SELECT    *
FROM    bi.ProcessMessageLog pml
INNER JOIN bi.[LogMessageType] lmt
   
ON    pml.[LogMessageTypeId] = lmt.[LogMessageTypeId]
WHERE    pml.[LogMessage] = 'Ski[LogMessageTypeName]of message: IApplicationCanceled'
AND        lmt.[LogMessageType] = 'Warning';

which is obviously not ideal. Thankfully that seems to have been solved with this latest release.

One disappointment about this new release is that the process for running tests as part of a CI build has not changed from the horrendously complicated process required previously. Check out my blog post Setting up database unit testing as part of a Continuous Integration build process [VS2010 DB Tools - Datadude] for instructions on how to do it. In that blog post I describe it as “fiddly” – I was being kind when I said that!

@Jamiet


Warning! Publish may fail on creation of a FOREIGN KEY constraint and then immediately succeed [SSDT]

$
0
0

I have stumbled across a nuance of SSDT that other users should be cognizant of. I published an SSDT database project onto an existing database that already had data in it but that Publish operation failed:

image

The error message was:

(10036,1): SQL72014: .Net SqlClient Data Provider: Msg 547, Level 16, State 0, Line 1 
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"ActualsDay_fct_ent_CustomerHierarchyLvl03_FK_PayTo".
The conflict occurred in database "PM_EDW", table "ent.CustomerHierarchyLvl03", column
'CstHierLvl03_EK'.

The command that caused the error was:

ALTER TABLE [fct].[ActualsDay] WITH CHECK CHECK CONSTRAINT [ActualsDay_fct_ent_CustomerHierarchyLvl03_FK_PayTo];

In other words SSDT created a FOREIGN KEY constraint in my database and then attempted to check that existing data satisfied that constraint (hence the WITHCHECK of the command above). There was some data that violated that constraint and the Publish operation failed.
This is good, I definitely want a Publish operation to fail under these circumstances.

If you want to understand more about WITHCHECK take a read of How to load related tables.

A problem occurred though when I next published because that Publish operation actually succeeded:

image

even though I hadn’t changed anything in the project! If I check out the metadata of that FOREIGN KEY:

SELECT	name,is_not_trustedFROMsys.foreign_keys  WHERE	name = 'ActualsDay_fct_ent_CustomerHierarchyLvl03_FK_PayTo' 

I see that [is_not_trusted] equals 1.

image

What does that mean, exactly? Well, SSMS’s table designer provides more useful information:

image

[is_not_trusted] means that my new FOREIGN KEY constraint has been created but the existing data has not been checked for compliance. Ouch! Not good, not good at all!


What’s going on here? If we break down the individual steps it becomes evident:

  1. First Publish operation starts
  2. FOREIGN KEY constraint gets created but without the WITH CHECK option
  3. FOREIGN KEY constraint is ALTERed to have the WITH CHECK option. This fails due to existing data violating the constraint and hence the entire Publish operation fails
  4. Second Publish operation starts
  5. Publish engine only checks to see that the FOREIGN KEY constraint exists, which it does. Hence, no action is taken
  6. Second Publish operation succeeds and I’m left with data that violates a newly created FOREIGN KEY constraint

This sequence of events can leave your database in a dangerous state and hence is something that SSDT users should be aware of. In my opinion this is a bug and I have raised it as such on Microsoft Connect: [SSDT bug] Publish will fail due to FK constraint and then succeed immediately after.

Be aware, be very aware!

@Jamiet

“Add as object” or “Add as script”? [SSDT]

$
0
0

In SQL Server Data Tools (SSDT) one way to create a new object is to right click on a folder in Solution Explorer and point to Add. Doing so will display this menu:

image

A number of options are offered for creating a brand new object (“function”, “table”, “stored proc” etc…) and one of them is “Script”. If your preference is to handcraft the DDL for every database object without resorting to a GUI then you may choose to use the “Script” option because, after all, every file is just a DDL script – why not write the thing from scratch? There is however one fundamental difference between the Script” option and all the other options that you should be aware of.

For the screenshot below I added a script and handcrafted a simple CREATE TABLE statement:

SNAGHTML760417d0

Notice that the table is defined in the dbo schema but it is not appearing in SQL Server Object Explorer under the dbo schema node. Why is that? The answer is actually pretty simple. If I select Script1.sql in Solution Explorer and hit F4 the properties window appears and we see this:

image

The Build Action property of the file is set to “None” which means that the file does not get included in a build and hence any objects defined within that file will not appear in our database. This is the default behaviour when you Add as script whereas the default behaviour when you explicitly add an object is to set Build Action=Build. That is the fundamental difference between adding a script and adding a specific object.

This is one of those nuances of SSDT that is an easy problem to spot when you know about it but can cause you to spend hours hunting around for a solution if you do not (believe me, I’ve been there). Be aware of it!

@Jamiet

Get to Know SQL Server 2012's SQL Server Data Tools [article published]

$
0
0

I recently wrote an article on SQL Server Data Tools for SQL Server Magazine and it has now been published online at Get to Know SQL Server 2012's SQL Server Data Tools. In the article I offer my thoughts and opinions on SQL Server Data Tools as it exists in SQL Server 2012.

image

Note that the article refers to SSDT database projects only, there is nothing in there pertaining to SSIS, SSAS or SSRS. If you find that confusing then you should probably go and at least read the first few paragraphs of the article where I try to alleviate some of that confusion.

Constructive feedback is, as always, very welcome.

@Jamiet

Responses to SSDT questions

$
0
0

My recent article Get to Know SQL Server 2012's SQL Server Data Tools prompted two questions to come to me via email and in the interests of sharing knowledge via search engines I thought I would answer them here rather than by simply replying by email (I hate that so much useful information gets trapped inside closed inboxes).


Question: How would you handle cases below, our main database has many objects already, we are using redgate source control to keep things under sourcecontrol but ssdt would be awesome.
Our database has some invalid stored procs etc, unfortunately we do not want to drop them, underlying objects either don't exists or has changed etc
There are linked servers or code referencing other objects stored in the database
There are staging table named automatically in the database and we do not want to include them in the project and not drop them or touch them in a deploy

JT: The overall question here seems to be “how do we prevent SSDT from DROPping sprocs and staging tables that are in the target database but are not in the SSDT project?” Fortunately SSDT has an option within it to allow exactly what the questioner requires. When an SSDT project is published one has the option to set some properties relating to that publish. One of the settings is “DROP objects in target but not in project”:

SNAGHTML5751f10

If that option is left unchecked (which is the default) then no objects will get removed from the target database.


Question: At my previous shop, I done a proof of concept with one of our databases, but never got it implemented as VS2012 (with SSDT) had not been released yet. Well, fast forward 9 or so months, and at my new shop (which is extremely agile) I've been tasked with setting up our db projects with SSDT so for the immediate short term goals/objectives we can;

  • Allow new or existing developers to be able to easily get the latest databases from source control downloaded from TFS, built and deployed onto our local sandbox db environments. This ideally will be done via a powershell script or something of the sort.
  • Be able to employ C.I. so that every night a database deployment is done to our system test servers.

3 days into it, and I've wrestled with 3 of our databases, reverse engineering them into TFS and getting them built etc. My question is, what are the best practices or guidelines for;

  1. Allowing only Windows authentication for the local deploys to the sandbox environment. i.e. is it best to have a script with all our team user logins in a script? How would the project recognise a team member which will create a login for them so once the project is deployed they can login to their local db?
  2. Using a 1-touch/click action (preferably outside of VS2010) to get latest, build project & deploy to local sandbox
  3. Same as above but to a system test server

JT: There are quite a few questions there. Firstly I’ll say that its great to hear of sandboxed environments and Continuous Integration (CI) being used – I openly advocate these techniques in my blog post Implementing SQL Server solutions using Visual Studio 2010 Database Projects – a compendium of project experiences.

Now, taking each question in turn:

  1. Windows Auth for local deploys. I’m not sure if there’s any recognised best practise here but if developers are working on local sandboxes I would assume they would have sysadmin rights so I’m not sure there’s a need to have a script of team logins. Perhaps I have misunderstood the question in which case please clarify in the comments below. I will say this though – I think its better to have a Windows group that you can move all of your devs in and out of rather than having to modify a script each time a user joins your team.
  2. 1-click get latest, build & deploy. Scripting your build & deploy is something else I advocate in the aforementioned blog post:

    Building and deploying your datadude projects within Visual Studio can become a real time hog; in my experience its not unusual for deployments to take many minutes and your Visual Studio environment will be unavailable for further development work during that time. For that reason I recommend investing some time in writing some msbuild scripts that will build and deploy your project(s) from the command-line.

    I’ll go further here and say that the script with which you use to build and deploy to your sandbox should be the same script as which you use for your production environment and everything in between. The script should take a parameter value to name the environment and then deploy appropriately.

  3. See 2.

Hope that is useful. Any questions? Please put them in the comments.

@Jamiet

My SQLBits Pre Conference Seminar - SSDT Database projects from the ground-up

$
0
0

Over the last year or so it will not have escaped my regular readers’ attention that much of my blogging has centred around SSDT database projects. SSDT (and its variously named forebears) is a tool that I have been using in some way, shape or form since 2007 and in that time I have built up what I feel is a sound body of knowledge and experience; I shall soon be sharing that knowledge in my first ever day-long seminar as part of the SQL Bits 11 Training Day on 2nd May 2013. I have titled the seminar SSDT Database projects from the ground-up; here is the abstract:

SQL Server Data Tools (SSDT) database projects bring SQL Server development into the modern era. Come along and learn how SSDT database projects can accelerate your SQL Server development and deployments. You will learn about declarative database development, code navigation, refactoring, automated builds, database unit testing and, most importantly, how you can make these tools work to your advantage.

If you come to my seminar you can expect lots of interactive demos for which I will share all the source code prior to the event; this means that you can go through the demos as I present them live – that’s a great way of learning new techniques.

As stated this is my first day-long seminar however I have been presenting publicly for some years now and have previously shared my speakers scores for public analysis. My most recent speaking engagement was at SQLBits 10 where my speaker scores were well above average:

image

The qualitative feedback included these comments:

  • The hour passed very quickly. Very good, interesting speaker.
  • This was a great session – I really like Jamie’s laid back presentation style
  • Informative session. Nicely showed off the new features and ways of working

That’s my short sales pitch over. I hope this piques your interest and if it does please sign up for my seminar when you register for SQLBits and I look forward to seeing you on the day.

@Jamiet

Viewing all 54 articles
Browse latest View live