Calling Stored Procedures from .NET Applications

Everybody knows how to call stored procedures from a .NET application. Right? But then, how often do you see stored procedures used to their full advantage in database applications? William Brewer goes through some of the basics, but uses PowerShell and IronPython as well as VB.NET as the example .NET applications just to freshen the subject up a bit, and avoids all mention of Northwind or AdventureWorks!

In this article, I’m going to illustrate how a stored procedure can be called from a .NET process, including all the ways in which data can be passed to the database. I’ll use PowerShell in the example code just because so many examples exist already in the other .NET languages, but I’ll add a version of the finished routine in IronPython and VB.NET.

When you  access a database application from a client, the chances are that you will need to call stored procedures  in the database layer. You’ll probably use the SQLClient  if you are using .NET, or SQL Native Client in unmanaged code. From Linux, you’d use JDBC.  In any event, all the hard work is done for you.

in .NET, there are three very similar ways of accessing SQL Server. If you want to access other databases such as MySQL, Access or SQLite, then you’ll use the net library System.Data.ODBC but we are going to use System.Data.SQLClient, as it supports all the current SQL Server datatypes.The third main approach is System.Data.OLEDB but but this is minority-interest.

Stored Procedures provide more alternatives in the way they can pass data back to the application. You can pass data and information

  • As one or more results
  • As a series of messages (e.g. DBCC)
  • As an integer return code
  • In output or input/output parameters.
  • In an error

Because of this, the interface can be slightly more complicated than just using Ad-Hoc SQL or views, and getting back single results. The payback is that Stored Procedures tend to work faster, are much more secure, are more economical with server memory, and can contain a lot more logic. Additionally, it makes teamwork easier: As long as the name of the stored procedure, what it does, and the parameters remain the same, it also allows someone else in the team to work on the database code without you having to change your client software.

Most Stored procedures are very simple, and are easy to access.  Stored procedures can, if so wished, return absolutely nothing, and such things are pretty simple to implement, but are not particularly common in actual use. Even if you are making a call to a database to record an event or update  a record, you are likely to want to know if it was successful or not, so already, you are likely to be tackling at least one transfer medium in the list I’ve given.

Let’s start off with a very simple application log consisting of a table and a stored procedure. We’ll refine it later. To try this out, just create a trial database in SSMS and use this code (I’m using SQL Server 2005) by pasting it into a query window and executing it…

Now we can easily call this logging stored procedure  from our client application just by executing the stored procedure. For some reason, the hardest part always seems to be the configuration string. It is worth getting this right before you start, maybe using an office application to test it. There are even websites that exist just to give sample Configuration strings, but they are mostly for ODBC. SQLClient is pretty easy.

 Once you have got the configuration string right, it is downhill all the way. Here is a simple PowerShell example. (Remember  to alter the connection string in the code to suit your server and database, of course.)

So we have called a stored procedure with a couple of parameters. Hmm. We’re not quite finished.  That connection string shouldn’t really be in code, as you’d have to change it if your credentials change. You can store connection strings in XML configuration files and read them in with the ConfigurationManager class.  More importantly, we need to be able to see any errors that happen. There are a number of ways of doing this. In PowerShell, though, we’re rather restricted. We’ll take an easy option and adapt the code slightly where the $cmd.Executenonquery() is called

This provides us with more information than we really need, but it keeps the code simple. Next, we worry about validating the input. There is no point in firing an error on invalid input as the application will want to know what type of  problem there was, and react accordingly. A lot of stored procedures send back a return code. We can always read that.

We’ll first make a slight change to the stored procedure so it returns 0 if it all went well, 1 if the log type was out of range, 2 if it failed to write to the log and 3 if something else happened….

Now, at the end of the client routine, we have access to this return code. In this example, we’ll just print it out but you’d want to react in the procedure according to the value of the return code. Apologies for not doing a complete worked example but we want to keep things simple just so we can illustrate the basics..

Okay, but what about getting something back from this routine? Let’s pretend that it would be useful to return the date on the database  at which the log entry was made.

Well, we have two choices. We can make the @LogString into an InputOutput variable or we can create an output variable just to hold the Date and time. Let’s do the latter, since using a variable for two purposes is a potential snare..

All we then had to do in order to get the value back was to add the following parameter

So, we’ve coped with input parameters, output parameters and return codes. Next we have to deal with a stored procedure that has one or more results.

Just to make life a bit more difficult for ourselves, we’ll pass back two results. We’ll return the values in the inserted row, and we’ll return the time that elapsed between log entries for the last ten log entries (we have the bones of a performance logging system here!).

This time, the stored procedure is beginning to bristle with outputs. It also is getting a lot nearer the sort of stored procedures I use. A stored procedure that returns a customer object that may have a number of contact numbers, addresses, notes, and purchases, and all this information is easier to transfer as a series of results rather than a Godzilla view, and the basic customer details such as the surrogate ID can easily be passed in an output variable.

So all we have to do now is to add the extra logic in the PowerShell script to get and display the two results. Here is the script.

The only task I haven’t shown is how to get the messages from the stored procedure. If you do PRINT statements, or you want to see other status messages (Normally you switch off the rowcount message using SET NOCOUNT  ON)  then you have to get hold of these messages. This is done by creating a SqlInfoMessageEventHandler delegate, identifying the method that handles the event,  to listen for the InfoMessage event on the SqlConnection class. Message-context information such as severity and state are passed as arguments to the callback, because from the system perspective, these messages are just like errors. At its simplist, you might do this…

But this cannot be done with PowerShell v1.

The routine translates easily into IronPython, but error-handling in Python (IronPython) is even more arcane than PowerShell, so I’ve omitted it.

We have not quite achieved all we want to yet as it would be nice to receive all those PRINT messages from SQL Server. To do this, you would do best to use either VB.NET or C#. The code just requires an event handler. This is explained very well here on MSDN- Working with Connection Events. Here is the complete code in VB

So you will see from this article that there are a number of different types of information we need to be able to get from a stored procedure. Some aspects are easy, and appear in demos all around the internet. Other information, such as messages, are fiendish and very language-dependent. Once you feel confident with output variables, return codes, and multiple results, you’ll find uses for them to make interacting with a database a lot easier.