HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Closing SQL connection for async operations

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
operationssqlasyncforclosingconnection

Problem

The following code executes asynchron on the SQL database. Is the closing of the connection implemented in the right way? Are there any missing features regarding connection handling which need to be added?

public void deleteData(Node node, User user)
        {
            SqlConnection connection = getConnection();
            connection.Open();
            string query = "DELETE FROM NodeUserData WHERE node = @nodeId and userId = @userId;";
            SqlCommand cmd = new SqlCommand(query, connection);
            cmd.CommandType = CommandType.Text;

            try
            {
                cmd.Parameters.AddWithValue("@nodeId ", node.id);
                cmd.Parameters.AddWithValue("@userId", user.id);

                List asynctasks = new List();
                asynctasks.Add(cmd.ExecuteNonQueryAsync());
                Task.Factory.StartNew(() => closeConnectionOnFinish(asynctasks, connection));

            }
            catch (Exception ex)
            {                
                writeExceptionToLogFile(ex);
            }       
        }


And the closeConnectionOnFinish:

public async  void closeConnectionOnFinish(List _tasks, SqlConnection connection)
        {
            try
            {
                await Task.WhenAll(_tasks);
                connection.Close();
            }
            catch (Exception ex)
            {
                writeExceptionToLogFile(ex);
            }
        }

Solution

No that isn't right. If your query throws an error you won't be closing the connection. Swallowing exceptions like that (even though you're logging it) is generally bad as well. How does the user know anything has gone wrong?

If you can, just use async and await with a using:

public async Task DeleteDataAsync(...)
{
     using (var connection = GetConnection())
     using (var cmd = /* ... */)
     {
         // ... trimmed
         await cmd.ExecuteNonQueryAsync();
     }
}


If you can't do that (I don't know why you couldn't) then you could do this:

cmd.ExecuteNonQueryAsync().ContinueWith(_ => connection.Close());


But you should be waiting for that task to finish.

Your naming is non standard: methods should be PascalCase.

async void is generally bad - there's no way for the caller to wait until the work is finished. You shouldn't use async void methods (except for event handlers).

Async methods should have the suffix Async and return a Task or Task.

Don't use Task.Factory.StartNew unless you want to specify advanced options; use Task.Run. However, don't use Task.Run for fake asynchrony - you'll just slow things down.

Code Snippets

public async Task DeleteDataAsync(...)
{
     using (var connection = GetConnection())
     using (var cmd = /* ... */)
     {
         // ... trimmed
         await cmd.ExecuteNonQueryAsync();
     }
}
cmd.ExecuteNonQueryAsync().ContinueWith(_ => connection.Close());

Context

StackExchange Code Review Q#120778, answer score: 7

Revisions (0)

No revisions yet.