Posts Tagged ‘SQL Server’

Generating fast test data in SQL Server

Wednesday, October 8th, 2008

Here is a quick and easy way to insert data into multiple tables joined by a foreign key constraint using only a SQL script.

I use this method often when I need to generate install scripts with static data or reusable and easily generated test data.

The method below uses the SQL Server @@identity variable to grab the last inserted id, assigning it to a temporary variable, and allowing it to be used in the second table to perform multiple row additions, linking each new row back to the parent record.

Without assigning it to a temporary variable as you will see below, the @@identity variable would reflect each new child row each time we did an insert, preventing us from linking the child rows back to our parent table.


DECLARE @fk_user INT;
DECLARE @fk_admin_role INT;
DECLARE @fk_user_role INT;

-- insert a user --
INSERT INTO users (username, password, firstname, lastname) VALUES('user_bill', 'password', 'billy', 'west');
SET @fk_user = @@identity;

-- insert some roles --
INSERT INTO roles (role_name) VALUES('user');
SET @fk_user_role = @@identity;

INSERT INTO roles (role_name) VALUES('admin');
SET @fk_admin_role = @@identity;

-- now populate the many to many table, with foreign keys from the stored values --
INSERT INTO users_roles (role_id, user_id) VALUES(@fk_user_role, @fk_user);
INSERT INTO users_roles(role_id, user_id) VALUES(@fk_admin_role, @fk_user);

The above now provides us with a script to quickly generate a basic multi role user, that we could use in a install script for our app or test script. We could now reload the data over and over again without needing to worry about specific primary keys and matching foreign keys, it is all done dynamically.

Each time we perform a insert we retrieve the last inserted primary key value and store it in a temporary variable. We then use these variables to combine and link our records via the “users_roles” table at the end once the required roles have been inserted.

[user] <– [users_roles] –>  [roles]

Ensuring safe database resource cleanup even in failure cases

Sunday, September 28th, 2008

Often when I see database code on forums and newsgroups I notice resource management in a situation of failure is non-existent. Exceptions can be handled gracefully and allow the application to continue running, so why should we ignore the mess of open connections and resources in the background that are not cleaned up in most cases due to cleanup code being bypassed when an exception is thrown.

Allow me to give a typical example…

public DataSet Load(string username)
{
    DataSet ds = null;
    try
    {
        SqlConnection conn = new SqlConnection(CONN_STRING);
        SqlDataAdapter da = new SqlCommand();
        SqlCommand cmd = new SqlDataAdapter(cmd);

        cmd.CommandText = "GetUser";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Connection = conn;

        cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = username;

        conn.Open();
        da.Fill(ds, "user");

        conn.Close();

    }
    catch (System.Exception ex)
    {
        throw ex;
    }

    return ds;
}

If you look above you may think, “we are closing the connection so what is the problem?” By closing the connection within the try block, we risk that the call to close on the connection object may never be called if an exception is thrown from our data adapter after the connection is opened. We are also are relying on the garbage collector to dispose all of our current database resources which isn’t very efficient.

So lets clean this up a bit with the addition of a ‘finally’ to our try catch.

public DataSet Load(string username)
{
    DataSet ds = null;
    SqlConnection conn = null;
    SqlDataAdapter da = null;
    SqlCommand cmd = null;

    try
    {
        conn = new SqlConnection(CONN_STRING);
        cmd = new SqlCommand();
        da = new SqlDataAdapter(cmd);

        cmd.CommandText = "GetUser";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Connection = conn;

        cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = username;

        conn.Open();
        da.Fill(ds, "user");

    }
    catch (System.Exception ex)
    {
    throw ex;
    }
    finally
    {
        if (conn != null)
        {
            if(conn.State == System.Data.ConnectionState.Open)
                conn.Close();
            conn.Dispose();
        }

        if(cmd != null)
            cmd.Dispose();
        if(da != null)
            da.Dispose();
    }

    return ds;
}

The advantage of using a finally block here is that whether or not an exception is thrown or is not thrown, the finally block will always be executed. This gives us the perfect place to put any final cleanup and connection code that we must guarantee will be executed, even in the event of an exception.

Note the ‘null’ checks on all objects before calling close and dispose methods on them. We do this because cannot guarantee that the objects have been initialized when they reach the finally block because the code could have thrown an exception very early within the try block before full initialization took place. We also need to place the object declarations outside of the try catch in order for them to be in proper scope for the finally block.

It is great to handle exceptions gracefully and continue application execution but you also need to be aware of what is going on behind the scenes with resources. Overtime with applications throwing many exceptions and many connections being left open, you are likely to see a slight performance hit in your applications, especially with a large user base.

Now this is all good, we now have successful closing of our connections, we have disposing even when exceptions are thrown, but personally I don’t like how long this code has become. Add a SqlDataReader to this code and it grows even more. So what can we do while still ensuring that clean up will happen?

C# offers a great solution called “using”. “Using” provides scope for your resources, and ensures that resources and even connections are both disposed and closed when they reach the end of their life. Underneath the hood a try finally is being wrapped around the objects, and providing the closing and disposing calls for you. Lets see what our example looks like with this new syntax.

public DataSet Load(string username)
{
    try
    {
        using(SqlConnection conn = new SqlConnection(CONN_STRING))
        {
            conn.Open();
            using(SqlCommand cmd = new SqlCommand("spGetUser", conn))
            {
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = username;

                using(SqlDataAdapter da = new SqlDataAdapter(cmd))
                {
                    da.Fill(ds, "users");
                }
            }
        }
    }
    catch (System.Exception ex)
    {
        throw ex;
    }
    return ds;
}

So as you can see our finally clause is now gone. We have also removed the need to declare our Sql objects at the beginning of our function and have moved the stored procedure and connection into the command object’s constructor. To me this provides much nicer code and organizes everything into nice workable chunks.

So in the end its really up to you which method you choose, but if you prefer organized code the latter will be the most likely choice. Remember, the more code you have to write the larger the chance for a bug to occur or a missed closing call.