Click here to Skip to main content
Click here to Skip to main content

Tool to script and store SQL Server objects in SourceSafe using SQL DMO and Visual SourceSafe automation

By , 5 May 2004
 

Introduction

Working with SQL Server databases in a huge group or enterprise environments with developers stepping out of line once in a while to make ad-hoc changes to tables, stored procedures or adding jobs and DTS will be a nightmare for admins and developers alike. Tracking changes to database structure is one of the most important piece of database development. Although sincere efforts are made in team development, crunching timelines and lack of resources tend to catch up with the developers once in a while to make an ad-hoc change to the database. Visual Studio and other client tools offer integration of SQL Server database with Visual SourceSafe. But many projects may not be able to afford the license or training time on these new tools. The attached DB Script Safe tool scripts and stores changes into Visual SourceSafe using SQL DMO and Visual SourceSafe automation. (Important note: This tool cannot be a substitute for regular database backups which include data.) This article attempts to demo the process of scripting and storing in SourceSafe. The attached code can be used by the developer community to cater their needs.

Demo application

DBScriptSafe Demo application

On startup, the application displays the above dialog box to configure parameters.

  1. Press <Get Servers List> button to fetch the list of SQL Server database instances.
  2. Give "blank" for database login and password to log into SQL Server using Windows login.
  3. Press <Connect> to connect to the database. On successful connection, the list of non-system databases are displayed and the <Script and Checkin Selected Databases> button is enabled.
  4. Browse and select a srcsafe.ini file to connect to Visual SourceSafe and give credentials and a project under which the scripts should be stored. Scripts will be stored according to the database and database object type, under <project>/<database>/<object type>/ directory inside SourceSafe.

It is required that the <project> directory exists in SourceSafe. Complete source code is included with the demo.

Using the code

SQLDMO and Visual SourceSafe automation library are added to the references of the project before using these objects. These are found under the COM tab of 'Add Reference' dialog box as 'Microsoft Source Safe 6.0 Type Library' and 'Microsoft SQLDMO Object Library'. This will create 2 namespaces SourceSafeTypeLib and SQLDMO which are used in the application. The SQLDMO.SQLServerClass is the top most class which is used to connect to a database instance, and once successfully connected is retained in the application as a member variable. The SQLServerClass.Databases collection is used to populate the list box.

    DBListView.Items.Clear();
    foreach (SQLDMO.Database db in m_sqlServer.Databases)
        if (! db.SystemObject)
            DBListView.Items.Add(db.Name);

The SQLDMO.Database class has a method called ScriptTransfer() which is at the heart of the script generation scheme. The signature of this method is:

ScriptTransfer(TransferClass transfer, 
    SQLDMO_XFRSCRIPTMODE_TYPE type, string path);

The TransferClass contains what objects are to be scripted and options when generating the script, like including headers or not. Most of the options are from SQLDMO_SCRIPT_TYPE enumeration. In the demo application code, this class is populated in ScriptEngine.ScriptDatabase(Database db) method. The TransferClass also has ScriptMessage and ScriptTransferPercentComplete events which are subscribed to by the DBScriptSafe class to display status messages.

    ScriptEngine.s_transfer.StatusMessage += 
        new TransferSink_StatusMessageEventHandler(s_transfer_StatusMessage);
    ScriptEngine.s_transfer.ScriptTransferPercentComplete +=
        new TransferSink_ScriptTransferPercentCompleteEventHandler(
                    s_transfer_ScriptTransferPercentComplete);

Coming to the Visual SourceSafe part, the project item which is root/project is either fetched, and if not found, is created by the following code:

    VSSItem VssDbItem = GetVssItem(vssPath, VSSItemType.VSSITEM_PROJECT);

Once this is established, the working folder for the SourceSafe project is determined by the type of objects being scripted which can be seen by the switch statement in the code.

    for (Db_Types dt = Db_Types.Defaults; dt<= Db_Types.Views; dt++)
    {
        workingFolder = m_workingFolder + @"\" + db.Name + @"\" + dt.ToString();
        System.IO.Directory.CreateDirectory(workingFolder);
        switch(dt)
        {
        case Db_Types.Defaults:
            s_transfer.CopyAllDefaults = true;
            GenerateScript(s_transfer, workingFolder, db);
            s_transfer.CopyAllDefaults = false;
            break;
        case Db_Types.Functions:
            s_transfer.CopyAllFunctions = true;
            GenerateScript(s_transfer, workingFolder, db);
            ....
            ....
        ...
        }
    }

All the script is generated by the following helper function in ScriptEngine class:

    private void GenerateScript(TransferClass tc, string folder, Database db)
    {
        db.ScriptTransfer(tc,
        SQLDMO_XFRSCRIPTMODE_TYPE.SQLDMOXfrFile_SingleFilePerObject,
                folder);
    }

The checkout, checkin and other operations on the SourceSafe are deliberately kept at the end of the sequence. Just in case the user tries to abort the scripting, we will have a chance to terminate the whole operation without touching the SourceSafe. Watch the flags and the sequence in the following code segment for the SourceSafe:

    VssDbItem.Checkout("DBScriptManager Automatic Checkout",
            workingFolder,
            (int)(VSSFlags.VSSFLAG_GETNO | VSSFlags.VSSFLAG_RECURSYES));

    VssDbItem.Checkin("DBScriptManager Automatic Checkin",
            workingFolder,
            (int)(VSSFlags.VSSFLAG_DELTAYES| VSSFlags.VSSFLAG_RECURSYES|
                    VSSFlags.VSSFLAG_DELYES));

    VssDbItem.UndoCheckout(workingFolder, 
            (int)(VSSFlags.VSSFLAG_GETNO | VSSFlags.VSSFLAG_DELYES| 
                VSSFlags.VSSFLAG_RECURSYES));

    VssDbItem.Add(workingFolder, "Created by DBScriptManager",
            (int) (VSSFlags.VSSFLAG_DELYES | VSSFlags.VSSFLAG_RECURSYES));

All the operations are done recursively from the project item. That is why the VSSFLAG_RECURYES is used in all the calls.

  1. First, the existing scripts are checked out without getting the files.
  2. All the changed scripts are checked in. This will check-in only new scripts into the SourceSafe.
  3. The UndoCheckout call next will undo checkout of any script which is missing from the last check-in.
  4. This leaves with adding all the new scripts which is done by the Add call at the end.

This simple 4 line code does all the work for us and demonstrates the power of Visual SourceSafe automation.

Enhancements suggested to demo project

Some of the enhancements to the demo project to make it more effective can be:

  • Making the program command line driven so that it can be scheduled to run under Windows Scheduler for periodic backups
  • Scripting the database itself
  • Scripts for Jobs and DTS at server level.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sriram Chitturi
Architect
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSQLSourceSafe-like for Vaultmembermarioavc9 Feb '06 - 11:47 
I've seen several tools for integrating SQL code (SPs, UDFs, triggers...) with SourceSafe. I am looking for something alike but for SourceGear's Vault[^] source control software. Vault is a software born to be a SourceSafe replacement, but likewise, does not implement this kind of feature. And other party tools, as SQLSourceSafe[^], are just focused on SourceSafe.
 
Does anybody know if such tool does exist?
Is there any open source project trying to implement this functionality?
Is anybody out there with the same need? (I'd really like to contribute) Maybe we can do something quick and dirty to have versioning control about SQL development on a Vault Repository.
 
I hope somebody will provide some direction here.
 
Mario V.
GeneralDupliation of scripts.memberGirish Patil19 Dec '05 - 20:09 
Infact this is a great tool. I am just helping to fine tune it.
 
When I tried it created duplicated file in VSS. For example in VSS *.TAB files were found under VIEWS as well as under TABLES folder and this behaviour was not consistant. But similar kind of issue happens anytime I run this tool.
 

 

 
Girish

GeneralGreat, simple tool!memberBrian Brennan29 Nov '05 - 10:37 
I'm a development manager/DBA that handles deployment of an enterprise database application. Along with myself, there are 4 other developers on my team that are routinely in SQL Analyzer building and tweaking stored procedures, functions, etc. Since even SQL Server 2005 seems to have not even an afterthought with regards to object source control (and I don't count that crude "Database Project" real source control), I've been looking for a tool that can simply scan a database, generate DDL scripts, and slam them into SourceSafe. I figure if I do this for each build just prior to deployment, even if I don't have the names of the developers making the changes, or every little change they make between builds at least I'll have something that I can roll back to if things go wrong.
 
I looked at a number of commercial products, including SQLSourceSafe, SQLDBControl, and a couple others, and none do what this simple tool does... They all seem to get lost in enhanced Query Analyzers and other frilly nonsense to realize that the database tools that come with SQL server don't respect the custom tool's notion of object check-in/check-out exclusivity, and changes they make outside their tool wind up getting lost.
 
Anyway, great work! And thanks especially for providing your code to codeproject.
GeneralOpen sourcememberckcatplague3 Nov '05 - 20:38 
Hi,
 
I'm interested in creating an open source MIT licensed project based on your code. I'm hoping your okay with that.
 
Thanks,
-Carlos
GeneralRe: Open sourcememberSriram Chitturi4 Nov '05 - 1:01 
Carlos,
I am glad to hear about it. Thanks for letting me know.
Can you please acknowledge the code in the Opensource and provide a link.
 
regards
sriram
 
Sriram Chitturi
GeneralRe: Open sourcememberckcatplague4 Nov '05 - 4:25 
Sriram,
 
I will definitely acknowledge your code and provide a link. I'll send you an email once I'm done so you can check it out.
 
Thanks,
Carlos
GeneralThis is great!!!memberkevnord14 Jun '05 - 11:31 
Thanks for posting this! It's very helpful!
I made it into a console app so I can schedule it, very handy!!!
 
Thanks again!
 
-k
GeneralRe: This is great!!!memberneil_b9 Dec '05 - 20:16 
Sounds just what I needSmile | :) Any chance of sharing it?
GeneralSQLSourceSafememberRayMu20021 Feb '05 - 9:24 
This is a product named SQLSourceSafe is available on the market. It integrated both SQL Server and SourceSafe. It have more functionalities than it is described there. For more information, please visit:
 
http://www.bestsofttool.com
 

 
Ray
GeneralSQL replication procedures make code failmemberjaviguillen25 May '04 - 9:34 
older SQL replication stored procedures like sp_replsync (which as flaged as user objects but in reality are system ones) cannot be scripted and break the code.... I am trying to find a way to exclude these objects when the GenerateScript function is being executed for all objects of certain type.... any ideas?Unsure | :~
GeneralOS and VSS version problemsmemberSriram Chitturi12 May '04 - 6:21 
See for an explanation in reply to 'Nick Horrocks' comment below
 
Sriram Chitturi
GeneralErrorssussNick Horrocks11 May '04 - 22:51 
Good article, but I found 2 problems when running the project.
 
a) If you try to script more than one database, an exception is generated when the temp directory is deleted. Solved this by moving the Directory Create & Delete outside of the for loop (Script() method).
 
b) If the VSS sub project for the DB doesn't exist the following exception is thrown
 
System.Runtime.InteropServices.COMException (0x80040000): Invalid OLEVERB structure
at SourceSafeTypeLib.VSSItemClass.NewSubproject(String Name, String Comment)
at DBScriptSafe.ScriptEngine.GetVssItem(String path, VSSItemType type) in c:\projects\visual studio projects\scriptsafe\dbscriptsafe\scriptengine.cs:line 184
System.Runtime.InteropServices.COMException (0x80040000): Invalid OLEVERB structure
at SourceSafeTypeLib.VSSItemClass.NewSubproject(String Name, String Comment)
at DBScriptSafe.ScriptEngine.GetVssItem(String path, VSSItemType type) in c:\projects\visual studio projects\scriptsafe\dbscriptsafe\scriptengine.cs:line 184
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in DBScriptSafe.exe
 
Path contains @"$\Database\DB_Name"
 

 

GeneralRe: ErrorsmemberSriram Chitturi12 May '04 - 6:20 
Nick Horrocks wrote:
a) If you try to script more than one database, an exception is generated when the temp directory is deleted. Solved this by moving the Directory Create & Delete outside of the for loop (Script() method).
 
Nick, this is a problem with the operating system holding up the directory and file handles. I can see it on Win2K, but not on Windows Advanced Server (my development platform).
Just remove the CreateDirectory() call in the ScriptEngine() constructor and try. It should solve the problem, otherwise you already have a fix Smile | :)
 
Nick Horrocks wrote:
b) If the VSS sub project for the DB doesn't exist the following exception is thrown ......
 
This problem was with Visual Source Safe 5.0 which takes only the last directory name in the path. In VSS 6.0 this is fixed and we can give the complete path.
If you are using VSS 5.0 use the following code snippet in the exception block in place of NewSubproject(..) line
 
int index = path.LastIndexOf('/');
if (index != -1) path = path.Substring(index+1);
item = m_vssRoot.NewSubproject(path, "Created by DBScriptManager");

 
Thanks for the feedback
 
Sriram Chitturi
GeneralRe: ErrorssussNick Horrocks12 May '04 - 10:38 

Thats a quick response....thanks
 
Sriram Chitturi wrote:
Nick Horrocks wrote:
b) If the VSS sub project for the DB doesn't exist the following exception is thrown ......
 
This problem was with Visual Source Safe 5.0 which takes only the last directory name in the path. In VSS 6.0 this is fixed and we can give the complete path.
If you are using VSS 5.0 use the following code snippet in the exception block in place of NewSubproject(..) line

 
I have VSS 6d (build 9848)
 
Tried your code but got exceptions where the project existed:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in DBScriptSafe.exe
 
Additional information: An item with the name $/Database/aladdinstats already exists
 
Added an empty try catch, now seems OK
 
try
{
System.Diagnostics.Debug.WriteLine(ex2.ToString());
int index = path.LastIndexOf('\\');
if (index != -1) path = path.Substring(index+1);
item = m_vssRoot.NewSubproject(path, "Created by DBScriptManager");
}
catch{}


GeneralArticle updatedmemberSriram Chitturi7 May '04 - 3:02 
Article is updated
 
Sriram Chitturi
GeneralUseful butsitebuilderPaul Watson6 May '04 - 21:30 
A useful tool, good idea and thank you for posting it but the article needs to explain how the app works and the interesting parts of the code.
 
regards,
Paul Watson
Bluegrass
South Africa
 
Christopher Duncan quoted:
"...that would require my explaining Einstein's Fear of Relatives"
 
Crikey! ain't life grand?

 
XmlTransformer, my latest CP article.
GeneralArticle updatedmemberSriram Chitturi7 May '04 - 3:01 
Thanks for the review.
I have rewritten the article and updated. Hope it helps.
 
Best regards,
 
Sriram Chitturi
GeneralRe: Article updatedsitebuilderPaul Watson7 May '04 - 3:29 
Fantastic, that is a definite improvement, thanks Sriram. Good work.
 
regards,
Paul Watson
Bluegrass
South Africa
 
Christopher Duncan quoted:
"...that would require my explaining Einstein's Fear of Relatives"
 
Crikey! ain't life grand?

 
XmlTransformer, my latest CP article.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 6 May 2004
Article Copyright 2004 by Sriram Chitturi
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid