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

SPGen - Stored Procedure Generator

By , 12 Dec 2002
 

Summary

SPGen is a simple Windows application which can generate the TSQL code for an INSERT or UPDATE Microsoft SQL Stored Procedures. Point it at a table, click the generate button and the code is generated for you.

The article covers some basic SQLDMO (SQL Database Management Object) methods and provides a slim .NET wrapper class around SQLDMO to help you in using SQLDMO.

SPGen in action
1. A screenshot of SPGen in action with a generated Stored Procedure in the main text box

Introduction

Writing the basics of Stored Procedures is mind numbing at best, even for DBAs. Megan Forbes, myself and a few others got into a heated rant about Microsoft SQL Server Enterprise Manager and it's extreme lack of SP tools and management. I decided to write a very simple app which takes away the drudge of typing in all the base code for an SP. When you are faced with a table of 50 fields and the need to create a simple UPDATE or INSERT SP, declaring all those parameters can be akin to agreeing to be the designated driver for the office Christmas party, i.e. deadly boring.

Using the application

Extract the downloaded demo zip, or re-compile the project, and run the executable.

  1. SPGen starts up and lists all locally registered SQL Servers in the top left drop down list
  2. Select, or type in, the SQL Server you want to connect to
  3. Enter in the User Name and Password for the SQL Server. If there is no Password needed then just leave the Password field untouched
  4. Click the Connect button
  5. SPGen will now attempt to connect to the specified SQL Server and list all the Databases
  6. Once the Databases are listed, expand the Database you wish to work with
  7. SPGen will now list all the Tables within the expanded Database
  8. Now expand the Table you wish to generate an SP for
  9. There will be two options; UPDATE or INSERT. Click the one you want
  10. SPGen will now attempt to retrieve the columns for the Table (but not display them) and generate the specified SP type
  11. Once generated the code is placed in the text box on the right and you can cut & paste that code into Microsoft SQL Enterprise Manager, or Microsoft SQL Server Query Analyzer

That is the extent of SPGen's functionality. You can generate SPs for other Tables, without having to re-connect, or you can connect to another SQL Server and generate SPs for that.

SQLDMOHelper

SQLDMOHelper is a simple class which returns basic information about a SQL Server to the caller. Really it just wraps up the common methods I needed from SQLDMO into easy to use .NET methods which return easily usable data. To this end it only returns data and does not provide any methods to save changes to a SQL Server, yet.

Using SQLDMO in your .NET app is actually very simple. All you need to do is add a reference to the Microsoft SQLDMO Object Library COM object in your project. You can then utilise SQLDMO methods with the interopped SQLDMO namespace. All very simple thanks to .NET.

Property: public Array RegisteredServers

This property returns a one-dimensional string array containing the names of all registered SQL Servers in the local domain.

SQLDMO provides a class called ApplicationClass which you can use to gather this list, like so;

ArrayList aServers = new ArrayList();
SQLDMO.ApplicationClass acServers = new SQLDMO.ApplicationClass();

for (int iServerGroupCount = 1; 
        iServerGroupCount <= acServers.ServerGroups.Count; 
        iServerGroupCount++)
    for (int iServerCount = 1; 
            iServerCount <= acServers.ServerGroups.Item(
               iServerGroupCount).RegisteredServers.Count; 
            iServerCount++)
        aServers.Add(acServers.ServerGroups.Item
            (iServerGroupCount).RegisteredServers.Item(iServerCount).Name);

return aServers.ToArray();

Quite simply a new instance of ApplicationClass is created. Then a for loop runs through each ServerGroups returned and then in the second for loop adds each RegisteredServer name to the aServers ArrayList. aServers is then returned to the caller to be consumed.

ArrayList really makes working with un-known length arrays very easy. You can basically redimension the array on the fly and then once you are finished use the ToArray method to return a valid Array.

Property: public Array Databases

Databases is a property which returns, as the name suggest, a one-dimensional string array of all Databases in a specified SQL Server.

ArrayList aDatabases = new ArrayList();

foreach(SQLDMO.Database dbCurrent in Connection.Databases)
    aDatabases.Add(dbCurrent.Name);

return aDatabases.ToArray();

A simple foreach loop is run against the SQLDMO.Databases collection which is returned from Connection.Databases.

Connection is a property of SQLDMOHelper which provides a SQLDMO Server connection. You need to use the Connect method to set the Connection property up. Also remember to use the DisConnect method to, wait for it, disconnect the connection.

Databases then returns the string array of Database names for your app to use.

Property: public Array Tables

Looks familiar, doesn't it? It is. The Tables property returns a one-dimensional string array of all Table names in a specified Database.

ArrayList aTables = new ArrayList();
SQLDMO.Database dbCurrent = (SQLDMO.Database)Connection.Databases.Item(
    this.Database, Connection);

foreach(SQLDMO.Table tblCurrent in dbCurrent.Tables)
    aTables.Add(tblCurrent.Name);
				
return aTables.ToArray();

Property: public SQLDMO.Columns Fields

The Fields property however is a bit different. Instead of returning a one-dimensional string array it returns a SQLDMO.Columns collection which provides a full range of details on all columns (fields) within a table.

The code though is even simpler than before as we are really just returning what SQLDMO provides and not translating it at all:

SQLDMO.Database dbCurrent = (SQLDMO.Database)
    Connection.Databases.Item(this.Database, Connection);
SQLDMO.Table tblCurrent = (SQLDMO.Table)
    dbCurrent.Tables.Item(this.Table, Connection);

return tblCurrent.Columns;

Columns is a collection of SQLDMO.Column objects which contain various properties and methods for working on a field in a table. In SPGen only Name, DataType and Length are used, but there are many more.

Properties: string ServerName, UserName, Password, DataBase and Table

These four properties of SQLDMOHelper are simply strings which hold what SQL Server, user name, password, database and table respectively the methods of SQLDMOHelper should work on. For instance Databases requires just ServerName, UserName and Password to be filled in to work. To use Fields though you also need Database and Table filled in so that Fields knows what to work on.

StoredProcedure

The StoredProcedure class provides just one method at the moment, Generate. This, finally, is the heart of SPGen and provides the functionality for returning valid Stored Procedure code.

Method: public string Generate

Parameters:

  • StoredProcedureTypes sptypeGenerate
    An enum indicating the type of Stored Procedure to generate. StoredProcedureTypes.INSERT and StoredProcedureTypes.UPDATE are currently valid choices
  • SQLDMO.Columns colsFields
    The Columns collection to use in the generation of the Stored Procedure
  • string sTableName
    The name of the Table the INSERT or UPDATE will affect

The code within Generate is pretty straight forward and consists largely of a StringBuilder being used to construct the Stored Procedure. On that note I found the AppendFormat method of StrinbBuilder to be highly effective for this kind of work.

Take this code for instance: sParamDeclaration.AppendFormat(" @{0} {1}", new string[]{colCurrent.Name, colCurrent.Datatype});. Without the AppendFormat method one would have to do the following: sParamDeclaration += " @" + colCurrent.Name + " " + colCurrent.Datatype; This latter way is terrible to debug and hard to understand when there is a whole page of similar code. The format functionality of StringBuilder (and just String itself) makes for much more manageable and understandable string manipulation.

StringBuilder also is faster than using sSample += "Not in kansas, " + sName + ", anymore";, especially when performing many string appends. Thanks to Tom Archer's fantastic sample chapter on using String in .NET, I certainly learnt a lot from it.

One other slight item of interest in the Generate method is this:

if (
 colCurrent.Datatype == "binary" || 
 colCurrent.Datatype == "char" || 
 colCurrent.Datatype == "nchar" || 
 colCurrent.Datatype == "nvarchar" || 
 colCurrent.Datatype == "varbinary" || 
 colCurrent.Datatype == "varchar")
    sParamDeclaration.AppendFormat("({0})", colCurrent.Length);

Basically in TSQL you must only declare the length of a parametre if it is one of the above data types. If you for instance try @NameFirst int(4) in TSQL you will get back an error as you may not declare the length of an int data type. At present I know of no way to programatically detect which data types must and must not have length declarations, therefore I have used the cumbersome if block you see above. I was hoping that SqlDbType would provide the neccesary information, but it does not, rendering it slightly less useful.

Apart from the the method is as stated mainly a big string manipulation method which takes in the provided fields, loops through them and returns a Stored Procedure of the type specified.

As I find more areas to automate in regards to Stored Procedures I hope to add new methods and helpers to this class.

Other Titbits

There is not much more to say or explain about SPGen, it really is a simple app. However following are two basically unrelated but still interesting titbits that you may find useful.

app.config

I have finally found a use for the app.config file beyond the usual. With SPGen you can open up app.config and modify the ServerName, UserName and Password application keys. SPGen will then read them in when the app starts and pre-fill the fields for you. This way if you have an often used SQL Server you can just fire up SPGen and hit connect without having to re-type the details in each time.

Obviously you want to be careful with the Password key especially, but I put it in with full confidence nobody would let their app.config file go wandering.

Code wise it is really quite simple:

NameValueCollection settingsAppSettings = 
    (NameValueCollection)ConfigurationSettings.AppSettings;

if (settingsAppSettings["ServerName"] != null && 
    settingsAppSettings["ServerName"] != "")
{
    selServers.Text = settingsAppSettings["ServerName"];
    dmoMain.ServerName = settingsAppSettings["ServerName"];
}

First I create a NameValueCollection collection, simply to make working with the configuration settings easier (i.e. instead of having to type ConfigurationSettings.AppSettings["key"] each time.) Then the code checks if there is a specified key value (I did not want the "Select Server" message being removed when there was no value) and then it sets the input field up to the value.

Nothing fancy, but it gives SPGen a small measure of customisation and gives your fingers a rest. By the way, on release build of SPGen app.config is automatically renamed to SPGen.exe.config, that is the file you need to edit to put in your SQL Server details.

TextBox PasswordChar

The PasswordChar property of the TextBox is pretty simple. You give it a char value that you want displayed instead of the actual text, e.g. *.

However, what if you want to reset that same TextBox so that it no longer masks the input? In SPGen I needed to do this as I, maybe wrongly, did not include labels for my input fields. MSDN provides a clue, but does not go on to show you exactly how. After a bit of stumbling around I figured it out;

char chResetPassword = (char)0;
txtPassword.PasswordChar = chResetPassword;

So you create a char of 0 (zero) and then assign that to the PasswordChar property.

It is quite obvious once you figure it out, but can be annoying before that.

Possible Improvements & Bugs

  • Allow the app to generate SPs from a SELECT query instead of just a Table selection
  • Allow the app to actually insert the SP into the database, saving you from having to cut & paste

Conclusion

Stored Procedures are very powerful but can be a tedious affair when multiple parameteres are required. Used in conjunction with Llewellyn Pritchard's DBHelper app though, you will have an end-to-end solution to working with Stored Procedures in an easy and fast manner.

SQLDMO is also a useful means of discovering and exploring SQL Servers and Databases. The main problem, in a .NET environment though, is that SQLDMO must be used through COM Interop, which is not an optimum situation. Hopefully in the near future a .NET SQLDMO will be released (though if you care to shed some light on how SQLDMO works I would be happy to write my own SQLDMO.NET class.)

If you have any ideas as to how to improve the app then please speak up.

License

This article, along with any associated source code and files, is licensed under The MIT License

About the Author

Paul Watson
Web Developer TSSG
Ireland Ireland
Member
Paul is an internet developer living in Waterford, Ireland though home is still South Africa.
 
He believes in self-taught programming skills, standards based thinking and in the power of the common man.
 
Oh, and he loves photography. Make sure you don't get caught in the corner of a party when he has that photographic gleam in his eye. And if you were wondering about that bed-head photograph, wonder no longer...

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   
QuestionWon't connect with Windows AuthenticationmemberAlexSLondon4 Apr '12 - 6:33 
Does not work with SQL Server 2008/localhost/Windows Authentication (won't connect).
GeneralMy vote of 5memberNickos_me7 Dec '11 - 21:42 
Now we have deadline, and your tool save any brilliant minutes. Thank you!
GeneralMy vote of 5memberCarneireiro18 Aug '11 - 7:52 
It saves a lot of work, specially when the tables have many columns.
GeneralPlease suggest Professional Touch Stored Procedure GeneratormemberGNWebSoft8 Feb '11 - 23:05 
There are many entry level generators but not professional or customized generator in my view. If anyone has any idea then please suggest.
GeneralRe: Please suggest Professional Touch Stored Procedure GeneratormemberTools4SQL.net14 Feb '11 - 20:45 
You can try Stored procedure generator of Tools4SQL.
 
They have some nice features like Joined SP, Combo SP, PK-FK Relationship columns, etc...
GeneralRe: Please suggest Professional Touch Stored Procedure Generatormemberyatinpatadiya16 Feb '11 - 2:49 
I have gone through Stored Procedure Generator. It is nice but it costs $100 which is bit more so please add features of it to current version.
GeneralRe: Please suggest Professional Touch Stored Procedure Generatormemberparas_prince15 Aug '11 - 21:19 
I think Tools4SQL.net's Stored Procedure Generator satisfies most of the requirement for SP Generation and moreover Demo doesnt expire. Shucks | :->
GeneralSQLDMO reference not active in VS2010memberppayal20 Aug '10 - 10:41 
Hi,
I found your article interesting.
I opened the source code in Visual studio 2010. It was missing refernce to SQLDMO. Please suggest how can run your source code in Visual studio 2010. Please reply urgently.
 
Regards.
QuestionError InteropServices SQL Server 2008memberjuliojesus2 Mar '10 - 19:52 
How can I fix the error:
 
Ocurrió System.Runtime.InteropServices.COMException
ErrorCode=-2147165949
HelpLink="SQLDMO80.hlp#700"
Message="[Microsoft][ODBC SQL Server Driver][SQL Server]Para conectar con este servidor debe utilizar Objetos de administración de SQL Server (SMO) o SQL Server Management Studio."
Source="Microsoft SQL-DMO (ODBC SQLState: 42000)"
StackTrace:
en SQLDMO.SQLServerClass.Connect(Object ServerName, Object Login, Object Password)
en Metasoftica.Data.SQLDMOHelper.Connect() en C:\HerramientasSQL\SQLDMOHelper.vb:línea 25
InnerException:
GeneralIt's Greate Utility for largest DBmemberkeyurmca@gmail.com25 Dec '09 - 23:44 
Hi Paul,
 
Thank you very much.
 
It's really nice tools for generating storeproce for large database.
GeneralGreat Tool, but needs somethingmemberOmarGamil30 Nov '09 - 0:01 
thanks for the effort and the great tool, it just needs to check identity fields so as not to generate them in the sp
 
good job
GeneralThanksmembermahmoud alam25 Nov '09 - 0:26 
Smile | :)
GeneralThanksmemberddatproject23 Nov '09 - 0:00 
what a very useful tool. Thanks you so much. I have save a lot of time
Generalsp gen problemmemberMember 29004945 Jan '09 - 0:33 
hi,
this tool is very nice
but don't work with schema and don't have template for sp
GeneralUserful Toolmemberashok_sole22 Dec '08 - 13:02 
Thank you for the Tool. It is very useful.
GeneralGreat Utilitymembershripad_117 Aug '08 - 12:40 
Paul..it's awsome utility saved lot of time for me. Thanks a lot!
Questionpjt doesn't build in VS2008membermrob12 Jul '08 - 8:42 
After making a few changes to the output, I tried to compile/build the pjt in VS2008. Got the following msg:
 
--------------------
Error 1
Warning as Error:
'System.Configuration.ConfigurationSettings.AppSettings'
is obsolete: 'This method is obsolete, it has been replaced by
System.Configuration!System.Configuration.ConfigurationManager.AppSettings'
 
frmMain.cs 41 67 SPGen
--------------------
 
Anyone know how to fix this so I can get the app working my way?
 
Thanks
AnswerRe: pjt doesn't build in VS2008sitebuilderPaul Watson2 Jul '08 - 11:51 
mrob1 wrote:
'System.Configuration.ConfigurationSettings.AppSettings'

 

mrob1 wrote:
System.Configuration.ConfigurationManager.AppSettings'

 
Hi Robert. Sorry but I no longer even have Visual Studio or Windows to test any of this out on. Based on the error message though you may be able to just replace all occurences of the first statement with the second statement. Seems they changed ConfigurationSettings to ConfigurationManager.
 
Apologies if this is obvious and you've already tried it.
 
regards,
Paul Watson
Ireland & South Africa
 
Fernando A. Gomez F. wrote:
At least he achieved immortality for a few years.

AnswerRe: pjt doesn't build in VS2008membermarc lang2 Feb '09 - 2:38 
Hi,
 
I had the same problem.
 
I just replaced the line throwing the error with:
 
NameValueCollection settingsAppSettings = (NameValueCollection)System.Configuration.ConfigurationManager.AppSettings;
 
I had to right click on the project and go to "Add Reference", looked in the ".NET" tab and added "System.Configuration".
It builds and runs after this.
 
Nice tool.
GeneralModified to use primary keys and generate delete procedurememberRatmilTorres17 Jan '08 - 7:19 
Hi.
I made a program like this one some years go in Visual Basic 6.0. I have modified your program to use primary keys and generate delete procedures.
Would you like me to send you the changes so I can a little credit? Smile | :)
GeneralCan't Connect to DB for memembericeangel8919 Jun '07 - 21:32 
it can't seem to work for me.... my database is currently in localhost\SQLEXPRESS and the prog says connection to DB failed. no user name & password.
Generaladded a new feature... DELETEmemberTim_Mackey5 Dec '06 - 2:20 
hi paul, greetings from dublin. really great code, this is just what i always wanted but never knew existed. i took the liberty of adding DELETE support, which was very straight forward, just posting it here if anyone is interested. my delete queries only delete by the identity column so the resulting query will look like this:
CREATE PROCEDURE Audits_DELETE
    @AuditID int
AS
DELETE FROM [Audits] 
WHERE    AuditID = @AuditID
GO
 
here are the changes i made:
 
step 1: add a new node for delete [in frmMain, tvwServerExplorer_BeforeExpand]
TreeNode treenodeTableDelete = new TreeNode("DELETE Stored Procedure", 2, 2);
treenodeTable.Nodes.Add(treenodeTableDelete);
 
step 2: add support for the DELETE nodes [in frmMain, tvwServerExplorer_AfterSelect]
// i found it simpler to replace the switch statement with a regex and enum parse
string query_type = Regex.Match(tnodeSelected.Text, @"\w+").Groups[0].Captures[0].Value;
StoredProcedureTypes spType = (StoredProcedureTypes)Enum.Parse(typeof(StoredProcedureTypes), query_type);
 
i made a few minor changes to SPGen.cs in order to support the DELETE syntax. rather than interleave all the changes, here is the whole file:
 
using System;
using System.Text;
 
namespace Bluegrass.Data
{	
	/// <summary>
	/// Supported Stored Procedure types
	/// </summary>
	public enum StoredProcedureTypes
	{
		UPDATE,
		INSERT,
		DELETE
	}
 
	/// <summary>
	/// Stored Procedure Helper class
	/// </summary>
	public class StoredProcedure
	{		
		/// <summary>
		/// Generates code for an UPDATE or INSERT Stored Procedure
		/// </summary>		
		public string Generate(StoredProcedureTypes sptypeGenerate, SQLDMO.Columns colsFields, string sTableName)
		{
			StringBuilder sGeneratedCode = new StringBuilder();
			StringBuilder sParamDeclaration = new StringBuilder();
			StringBuilder sBody = new StringBuilder();			
			StringBuilder sINSERTValues = new StringBuilder();
 
			// Setup SP code, begining is the same no matter the type
			sGeneratedCode.AppendFormat("CREATE PROCEDURE {0}_{1}", new string[]{sTableName, sptypeGenerate.ToString()});			
			sGeneratedCode.Append(Environment.NewLine);
 
			// Setup body code, different for UPDATE and INSERT
			switch (sptypeGenerate)
			{
				case StoredProcedureTypes.INSERT:
					sBody.AppendFormat("INSERT INTO [{0}] (", sTableName);
					sBody.Append(Environment.NewLine);
 

					sINSERTValues.Append("VALUES (");
					sINSERTValues.Append(Environment.NewLine);
					break;
				
				case StoredProcedureTypes.UPDATE:
					sBody.AppendFormat("UPDATE [{0}]", sTableName);					
					sBody.Append(Environment.NewLine);
					sBody.Append("SET");
					sBody.Append(Environment.NewLine);
					break;
 
				case StoredProcedureTypes.DELETE:
					sBody.AppendFormat("DELETE FROM [{0}] ", sTableName);
					sBody.Append(Environment.NewLine);
					sBody.Append("WHERE");
					break;
				
			}
			 						
			foreach (SQLDMO.Column colCurrent in colsFields)
			{
				// only list identity columns for delete statements
				if(sptypeGenerate == StoredProcedureTypes.DELETE && !colCurrent.Identity)
					continue;
 
				// Param Declaration construction
				sParamDeclaration.AppendFormat("    @{0} {1}", new string[]{colCurrent.Name, colCurrent.Datatype});				
				
				// Only binary, char, nchar, nvarchar, varbinary and varchar may have their length declared								
				if (
					colCurrent.Datatype == "binary" || 
					colCurrent.Datatype == "char" || 
					colCurrent.Datatype == "nchar" || 
					colCurrent.Datatype == "nvarchar" || 
					colCurrent.Datatype == "varbinary" || 
					colCurrent.Datatype == "varchar")
					sParamDeclaration.AppendFormat("({0})", colCurrent.Length);
				
				sParamDeclaration.Append(",");
				sParamDeclaration.Append(Environment.NewLine);
 
				// Body construction, different for INSERT and UPDATE
				switch (sptypeGenerate)
				{
					case StoredProcedureTypes.INSERT:						
						sINSERTValues.AppendFormat("    @{0},", colCurrent.Name);						
						sINSERTValues.Append(Environment.NewLine);
 
						sBody.AppendFormat("    {0},", colCurrent.Name);						
						sBody.Append(Environment.NewLine);
						break;
 
					case StoredProcedureTypes.UPDATE:
					case StoredProcedureTypes.DELETE:
						sBody.AppendFormat("    {0} = @{0},", new string[]{colCurrent.Name, });											
						sBody.Append(Environment.NewLine);
						break;
				}
			}
 
			// Now stitch the body parts together into the SP whole			
			sGeneratedCode.Append(sParamDeclaration.Remove(sParamDeclaration.Length - 3, 3));			
			sGeneratedCode.Append(Environment.NewLine);
			sGeneratedCode.Append("AS");
			sGeneratedCode.Append(Environment.NewLine);
			sGeneratedCode.Append(sBody.Remove(sBody.Length -3, 3));			
			if (sptypeGenerate == StoredProcedureTypes.INSERT)
			{
				sGeneratedCode.Append(")");
				sGeneratedCode.Append(Environment.NewLine);
				sGeneratedCode.Append(sINSERTValues.Remove(sINSERTValues.Length - 3, 3));
				sGeneratedCode.Append(")");	
			}
			sGeneratedCode.Append(Environment.NewLine);
			sGeneratedCode.Append("GO");
					
			return sGeneratedCode.ToString();
		}
	}
}
 
 
sound.
tim
GeneralRe: added a new feature... DELETEmemberkiki59625 Apr '07 - 4:50 
Voici la gestion du DELETE et surtout une meilleure gestion des colonnes IDENTITY et des colonnes inclues en clé primaire
Les colonnes Identity ne sont plus insérées/updatées et les restrictions se basent sur les clés primaires.
 
using System;
using System.Text;
 
namespace Bluegrass.Data
{
///
/// Supported Stored Procedure types
///
public enum StoredProcedureTypes
{
UPDATE,
INSERT,
DELETE
}
 
///
/// Stored Procedure Helper class
///
public class StoredProcedure
{
 

private void AddParameterDeclaration(StringBuilder sParamDeclaration, SQLDMO.Column colCurrent,bool onlyPrimaryKey)
{
 
if (onlyPrimaryKey && !colCurrent.InPrimaryKey) return;
 
if (!colCurrent.Identity)
{
if (sParamDeclaration.Length > 0)
{
sParamDeclaration.Append(',').Append(Environment.NewLine);
}
 
// Param Declaration construction
sParamDeclaration.AppendFormat(" @{0} {1}", colCurrent.Name, colCurrent.Datatype);
 
// Only binary, char, nchar, nvarchar, varbinary and varchar may have their length declared
if (
colCurrent.Datatype == "binary" ||
colCurrent.Datatype == "char" ||
colCurrent.Datatype == "nchar" ||
colCurrent.Datatype == "nvarchar" ||
colCurrent.Datatype == "varbinary" ||
colCurrent.Datatype == "varchar")
sParamDeclaration.AppendFormat("({0})", colCurrent.Length);
}
}
private void AddParameterWhere(StringBuilder sWhereClause, SQLDMO.Column colCurrent)
{
if (colCurrent.InPrimaryKey)
{
if (sWhereClause.Length == 0)
sWhereClause.AppendFormat(" WHERE {0} = @{0} ", colCurrent.Name);
else sWhereClause.AppendFormat(" AND {0} = @{0} ", colCurrent.Name);
sWhereClause.Append(Environment.NewLine);
}
}
private void AddParameterUpdate(StringBuilder sUpdateClause, SQLDMO.Column colCurrent)
{
if (!colCurrent.Identity)
{
if (sUpdateClause.Length == 0)
sUpdateClause.AppendFormat(" SET {0} = @{0} ", colCurrent.Name);
else sUpdateClause.AppendFormat(" ,SET {0} = @{0} ", colCurrent.Name);
sUpdateClause.Append(Environment.NewLine);
}
}
private void AddParameterInsert(StringBuilder sInsertClause,StringBuilder sInsertValues, SQLDMO.Column colCurrent)
{
if (!colCurrent.Identity)
{
if (sInsertClause.Length == 0)
{
sInsertClause.AppendFormat("{0}", colCurrent.Name);
sInsertValues.AppendFormat("@{0}", colCurrent.Name);
}
else
{
sInsertClause.AppendFormat(",{0}", colCurrent.Name);
sInsertValues.AppendFormat(",@{0}", colCurrent.Name);
}
}
}
 
///
/// construit les requêtes SQL INSERT, UPDATE et DELETE
///

///
///
///
///
public string Generate(StoredProcedureTypes sptypeGenerate, SQLDMO.Columns colsFields, string sTableName)
{
StringBuilder sGeneratedCode = new StringBuilder();
StringBuilder sParamDeclaration = new StringBuilder();

StringBuilder sInsertValues = new StringBuilder();
StringBuilder sInsertClause = new StringBuilder();
StringBuilder sUpdateClause = new StringBuilder();
StringBuilder sWhereClause = new StringBuilder();
 

 
switch (sptypeGenerate)
{
case StoredProcedureTypes.UPDATE:
{
foreach (SQLDMO.Column colCurrent in colsFields)
{
/* generation des paramètres */
AddParameterDeclaration(sParamDeclaration, colCurrent,false);
/* generation du code */
AddParameterUpdate(sUpdateClause, colCurrent);
/* generation des restrictions */
AddParameterWhere(sWhereClause, colCurrent);
}
break;
}
case StoredProcedureTypes.INSERT:
foreach (SQLDMO.Column colCurrent in colsFields)
{
/* generation des paramètres */
AddParameterDeclaration(sParamDeclaration, colCurrent, false);
/* generation du code */
AddParameterInsert(sInsertClause, sInsertValues, colCurrent);
}
break;
case StoredProcedureTypes.DELETE:
foreach (SQLDMO.Column colCurrent in colsFields)
{
/* generation des paramètres */
AddParameterDeclaration(sParamDeclaration, colCurrent,true);
/* generation des restrictions */
AddParameterWhere(sWhereClause, colCurrent);
}
break;
}
 
// Setup SP code, begining is the same no matter the type
sGeneratedCode.AppendFormat("CREATE PROCEDURE {0}_{1}", sTableName, sptypeGenerate.ToString());
sGeneratedCode.Append(Environment.NewLine);
 
//déclaration des paramètres
if (sParamDeclaration.Length > 0)
{
sGeneratedCode.AppendFormat("({0})", sParamDeclaration);
sGeneratedCode.Append(Environment.NewLine);
}
sGeneratedCode.Append(" AS ");
sGeneratedCode.Append(Environment.NewLine);
 

// Setup body code, different for UPDATE and INSERT
switch (sptypeGenerate)
{
case StoredProcedureTypes.INSERT:
sGeneratedCode.AppendFormat("INSERT INTO [{0}] ({1}) VALUES({2})", sTableName, sInsertClause, sInsertValues);
sGeneratedCode.Append(Environment.NewLine);
break;
case StoredProcedureTypes.UPDATE:
sGeneratedCode.AppendFormat("UPDATE [{0}] {1} {2} {3}", sTableName, Environment.NewLine,sUpdateClause, sWhereClause);
sGeneratedCode.Append(Environment.NewLine);
break;
case StoredProcedureTypes.DELETE:
sGeneratedCode.AppendFormat("DELETE FROM [{0}] {1} {2}", sTableName, Environment.NewLine,sWhereClause);
sGeneratedCode.Append(Environment.NewLine);
break;
}
 
sGeneratedCode.Append(Environment.NewLine);
sGeneratedCode.Append("GO");
sGeneratedCode.Append(Environment.NewLine);
 

return sGeneratedCode.ToString();
}
}
}
GeneralOpen Source SQLDMO "Wrapper" Projectmemberchanthailong5 Nov '06 - 10:17 
I would like everyone reading this article to know about a new open source project: SQLDMO.NET - a SQL Database Management Object for .NET.
 
SQLDMO.NET is meant to be a light weight .NET wrapper of the (COM) SQLDMO object that allows .NET developers the ability to manage SQL Server 7.0/2000 databases. This library provides an alternative to using the full strength of SQL SMO (e.g. to avoid installing SQL SMO and/or its prerequisites such as SP2 on Windows XP), or dealing with SQLDMO directly via interop. SQLDMO.NET is, and will be, characterized by a limited set of extremely practical services, such as:
 
. Finding all SQL Servers on a local network node
. Enumerating registered SQL Server groups and servers
. Creating a database via a SQL script
. Generating a SQL script of DDL for an existing database
. Adding/Deleting Stored Procedures, Tables, Views, etc, etc...
. Creating a new user login
 
The project is being hosted at http://code.google.com/p/sqldmonet/. Please feel free to check it out. We are in the early stages and anyone who wants to join and/or contribute is more than welcome!
 
...
GeneralRe: Open Source SQLDMO "Wrapper" ProjectmemberNetDefender9 Oct '09 - 23:22 
Thanks
GeneralOpen Source SQLDMO "Wrapper" Projectmemberchanthailong5 Nov '06 - 10:16 
I would like everyone reading this article to know about a new open source project: SQLDMO.NET - a SQL Database Management Object for .NET.
 
SQLDMO.NET is meant to be a light weight .NET wrapper of the (COM) SQLDMO object that allows .NET developers the ability to manage SQL Server 7.0/2000 databases. This library provides an alternative to using the full strength of SQL SMO (e.g. to avoid installing SQL SMO and/or its prerequisites such as SP2 on Windows XP), or dealing with SQLDMO directly via interop. SQLDMO.NET is, and will be, characterized by a limited set of extremely practical services, such as:
 
. Finding all SQL Servers on a local network node
. Enumerating registered SQL Server groups and servers
. Creating a database via a SQL script
. Generating a SQL script of DDL for an existing database
. Adding/Deleting Stored Procedures, Tables, Views, etc, etc...
. Creating a new user login
 
The project is being hosted at http://code.google.com/p/sqldmonet/. Please feel free to check it out. We are in the early stages and anyone who wants to join and/or contribute is more than welcome!
GeneralNice but it needs more work..memberk_nanev@hotmail.com3 Aug '06 - 12:00 
I really liked it but i think in real life you will more than just insert and update SPs. For instance: Delete, Update if exist or Insert if doesnt exist, custom querres.
AnswerRe: Nice but it needs more work..memberchanthailong5 Nov '06 - 10:22 
This is exactly the sort of thing we are trying to expand upon at the SQLDMO.NET project: http://code.google.com/p/sqldmonet/.
 
Feel free to check out our latest code, and contribute some of your ideas for features/improvements. For example, the ability to Delete, Update (if exists) or Insert (if doesn't exist) custom queries is something you could add to our issue tracker (as type "Enhancement").
GeneralRe: Nice but it needs more work..memberjohn.burban15 Dec '07 - 3:43 
Definetly a nice tool.
 
Our dev department uses OxyGen Code (http://www.techinceptions.com/codegenerator.html).
This is not a free tool though. The advantage of OxyGen Code is that you can capture relationships between tables and also generates C# code for you.
Generalminor bugs, but can't complain, it's free !!memberprideaux907 Feb '06 - 17:20 
it is very useful and saved me lots of typing and typos! thanks.
 
bugs: did not handle some of my field names
e.g.
[--my field name--]
1800_1300_fieldname

GeneralWindowsAuthenticationsussdownhillchris2 Sep '05 - 17:31 
My instance of SQL uses windows authentication and SPGen requires a user name and password to connect. I have tried connecting with my windows login details too. Is there any other work around for this problem?Confused | :confused:
GeneralRe: WindowsAuthenticationmemberstmarti26 Sep '05 - 0:17 
Download the source not the compiled executable.
Open SQLDMOHelper.cs in vs.net, find the following method:
 
public void Connect()
{
Connection.Connect(ServerName, UserName, Password);
}

 
replace with:
 
public void Connect()
{
Connection.LoginSecure = true;
Connection.Connect(ServerName, null, null);
}

 
Recompile, and now all connection are trusted. /This is the easiest path, little more effort needs to implement a checkbox indicating trusted and nontrusted connection./
 

GeneralReset PasswordCharmemberBabu Aboobacker E.I23 Mar '05 - 15:29 
Thanks for providing the code snippet to reset the PasswordChar. Smile | :)
 

May GOD accept all our good deeds, and keep us in the right path.


Babu Aboobabacker E.I


GeneralRe: Reset PasswordCharmemberBabu Aboobacker E.I23 Mar '05 - 15:37 
// Reset password char
editTextBox.PasswordChar = '\0';
 

Babu Aboobabacker E.I


GeneralHeymemberAlexander German17 Nov '04 - 5:59 
Nothing to say about it. Simply f@c..g cool. I was thinking about doing something like this but you went way ahead. Keep kicking.Smile | :)
 
Alexander German
GeneralColorized SintaxememberLaudeci Oliveira20 Oct '04 - 8:03 
Yeah, SQL Server have such wizard to create stored procedure, but the code generated isnt clear like that one... i like it so much...
 

Think about put colorized sintaxe in Generated code Wink | ;)
 
Laudeci Oliveira
Microsoft Certified Professional
Questionhow i get the current connectionmemberropy15 Oct '04 - 1:14 
hi,
very nice work ,
but iam trying to add an execute button to exceute the the stored procedure on the current connection.
my question is
how i use the current connectionto do this
how i get the connection.
note i do a little change to serve development
is connect only once not before every action
so how i use this current connection
an thanks in advance
 

 


AnswerRe: how i get the current connectionmemberropy15 Oct '04 - 2:14 
hi
thanks all
i know how i do it
by creating this method on the SQLDMOHelper
and call it from button click
 
public void ExecutSp(String comm)
{
Connection.ExecuteImmediate(comm,0,Connection);

}
GeneralVery CoolmemberRooster10115 Apr '04 - 20:59 
Very Cool App, Saving me stacks of time on Code Generation Poke tongue | ;-P ;P;P

 
from Durbs
 

GeneralThis is a life-saver!memberSeevo28 Oct '03 - 5:50 
This is a very useful app - easy to tweak as well. Saved me a great deal of menial sp coding!
 
Thanks!
 
PS: Is anyone posting changes to the source i.e. open source type deal? If so, where - I've made some pretty useful changes others might like...
 
Thanks Alot
Seevo
GeneralRe: This is a life-saver!sitebuilderPaul Watson28 Oct '03 - 5:58 
Wow, thanks for the comment Seevo, made my day Smile | :)
 
There is no open author project on this article and it's code but I would be very happy to update it with your tweaks (and much due credit to you). Just email me direct and we can sort something out. Maybe make you a co-author or whatever works.
 
regards,
Paul Watson
Bluegrass
South Africa
 
Miszou wrote:
I have read the entire internet. on how boring his day was.
 
Crikey! ain't life grand?

GeneralRe: This is a life-saver!memberSeevo28 Oct '03 - 6:00 
Sounds good - I'll get it together and contact you.
 
Thanks Alot
Seevo
GeneralRe: This is a life-saver!memberQuantumQuinn27 Dec '05 - 13:43 
Great mini-app
 
I also made some tweaks to it.
 
I accomplished some of your proposed updates.
 
Quantum Quinn Inc.
GeneralRe: This is a life-saver!memberThomas Wells19 Jan '07 - 9:56 
I agree. I've converted Mustafa Magdy's version to VB (where I'm more comfortable). This will be a great tool for us.
 
Thanks Paul
GeneralPaid back an old debteditorNishant S11 Sep '03 - 4:47 
Paul
 
I dont know if you remember this, but my first ever edited article was edited by you Smile | :) And I havent updated it later - it still says Editor - Paul Watson and I am quite happy to see your name there.
 
I remember how you once asked me in jest to pay it back by editing your MC++ competition article but unfortunately Chris edited that before I got my hands on it.
 
Well this is it Paul. Pay back time.
 
Good article. I only had to rectify the scrolling and correct a couple of typo-errors.
 
Thanks Paul
Regards
Nish
 
p.s. There are things I forget. And there are things I never forget. Your editing my Services article the day you became editor is something I somehow remember. Something so nice and emotional about that day. Weird eh? Smile | :) Those were Sonork chatting days too I guess.
 

Extending MFC Applications with the .NET Framework [NW] (coming soon...)
Summer Love and Some more Cricket [NW] (My first novel)
Shog's review of SLASMC [NW]
Come with me if you want to live

GeneralRe: Paid back an old debtsitebuilderPaul Watson11 Sep '03 - 5:27 
It is my honour to have you editing this article and my pleasure to have edited your first article. Who knew at that time what a power house of knowledge you would become to CP. I can't tell you how pleased I was to hear that you had become a part of the CP team proper. I think there are even better days ahead of us and so we must not miss the Sonork days but rather just remember them fondly.
 
So thank you again Nish Smile | :)
 
Paul Watson
Bluegrass
Cape Town, South Africa
Crikey! ain't life grand?
GeneralHandling Identity Columns and Primary Keyssusswebdev9308 Apr '03 - 15:33 
This is a pretty good little generator. I think there are a couple of additions that would make this an awesome generator.
 
One feature to add to the INSERT procedure, would be to handle identity columns. Since you can't insert or update an identity column anyway (without setting the allow identity insert option), it would be nice if the generator handled this. Good behavior for this in a .NET development environment would be to leave the identity column out of parameter list and perform a scalar return of the identity value generated during the insert. i.e. SELECT CategoryID = SCOPE_IDENTITY()
 
SCOPE_IDENTITY() is a SQL2000 feature so maybe giving an option of SQL version somewhere optionally generate it with a SELECT CategoryID = @@IDENTITY
 
The other feature that I'd suggest is for the UPDATE procedure. Here it would be good to detect the primary key fields for the table and add them to a WHERE clause in the UPDATE statement. Very rarely do we ever use an UPDATE statement without a WHERE clause.
 
Hope those features get into the next version... or if I get inspired I'll change the code myself. Thanks for developing this generator though...anything I don't have to type is better than nothing!!
 
Andrew
 

GeneralRe: Handling Identity Columns and Primary KeyssitebuilderPaul Watson8 Apr '03 - 20:36 
Thanks for the ideas Andrew, much appreciated. I cannot promise anything though Smile | :)
 
Paul Watson
Bluegrass
Cape Town, South Africa
Macbeth muttered:
I am in blood / Stepped in so far, that should I wade no more, / Returning were as tedious as go o'er
Shog9:
Paul "The human happy pill" Watson
GeneralRe: Handling Identity Columns and Primary Keysmemberbkavanaugh22 Apr '03 - 9:37 
The code for handling identity fields is pretty easy, actually. I just modified it myself. In your foreach loop in SPGen.cs, "colCurrent.Identity" will tell you if the current column is an Identity field.
 
StringBuilder sWhereClause = new StringBuilder( ); // declared outside of foreach loop
 
if( !colCurrent.Identity || sptypeGenerate == StoredProcedureTypes.UPDATE ) {
// Param Declaration construction
sParamDeclaration.AppendFormat(" @{0} {1}", new string[]{colCurrent.Name, colCurrent.Datatype});
// Only binary, char, nchar, nvarchar, varbinary and varchar may have their length declared
if (
colCurrent.Datatype == "binary" ||
colCurrent.Datatype == "char" ||
colCurrent.Datatype == "nchar" ||
colCurrent.Datatype == "nvarchar" ||
colCurrent.Datatype == "varbinary" ||
colCurrent.Datatype == "varchar")
sParamDeclaration.AppendFormat("({0})", colCurrent.Length);

sParamDeclaration.Append(",");
sParamDeclaration.Append(Environment.NewLine);
}
 
if( colCurrent.Identity && sptypeGenerate == StoredProcedureTypes.UPDATE ) {
// store the where clause
sWhereClause.Append("WHERE");
sWhereClause.Append(Environment.NewLine);
sWhereClause.AppendFormat(" {0} = @{0}", colCurrent.Name);
} else if( !colCurrent.Identity ) {
// Body construction, different for INSERT and UPDATE
switch (sptypeGenerate) {
...
}
}
 

Then, at the end where you're stitching it back together:
 
if (sptypeGenerate == StoredProcedureTypes.INSERT) {
sGeneratedCode.Append(Environment.NewLine);
sGeneratedCode.Append(sINSERTValues.Remove(sINSERTValues.Length - 3, 3));
sGeneratedCode.Append(Environment.NewLine);
sGeneratedCode.Append(")");
} else {
sGeneratedCode.Append(Environment.NewLine);
sGeneratedCode.Append(sWhereClause);
sGeneratedCode.Append(Environment.NewLine);
}

QuestionWhy use an SP?memberJörgen Sigvardsson18 Mar '03 - 11:11 
Why do you prefer using an SP to do UPDATES and INSERTS? All I see is a difference in syntax. Am I missing the point? Confused | :confused:
 
--
Shine, enlighten me - shine
Shine, awaken me - shine
Shine for all your suffering - shine

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.130516.1 | Last Updated 13 Dec 2002
Article Copyright 2002 by Paul Watson
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid